Skip to content

Commit 7d0dcee

Browse files
committed
PoC: generic infix operators
1 parent 6d78c58 commit 7d0dcee

15 files changed

+250
-177
lines changed

jscomp/build_tests/super_errors/expected/math_operator_constant.res.expected

+2-8
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,8 @@
77
3 │ let x = num + 12.
88
4 │
99

10-
This value has type: float
11-
But it's being used with the + operator, which works on: int
12-
13-
Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.
14-
15-
Possible solutions:
16-
- Ensure all values in this calculation has the type int. You can convert between floats and ints via Belt.Float.toInt and Belt.Int.fromFloat.
17-
- Make 12. an int by removing the dot or explicitly converting to int
10+
This has type: float
11+
But it's expected to have type: int
1812

1913
You can convert float to int with Belt.Float.toInt.
2014
If this is a literal, try a number without a trailing dot (e.g. 20).
Original file line numberDiff line numberDiff line change
@@ -1,20 +0,0 @@
1-
2-
We've found a bug for you!
3-
/.../fixtures/math_operator_int.res:3:9-11
4-
5-
1 │ let num = 0.
6-
2 │
7-
3 │ let x = num + 12.
8-
4 │
9-
10-
This has type: float
11-
But it's being used with the + operator, which works on: int
12-
13-
Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.
14-
15-
Possible solutions:
16-
- Ensure all values in this calculation has the type int. You can convert between floats and ints via Belt.Float.toInt and Belt.Int.fromFloat.
17-
- Change the operator to +., which works on float
18-
19-
You can convert float to int with Belt.Float.toInt.
20-
If this is a literal, try a number without a trailing dot (e.g. 20).
Original file line numberDiff line numberDiff line change
@@ -1,16 +0,0 @@
1-
2-
We've found a bug for you!
3-
/.../fixtures/math_operator_string.res:1:9-15
4-
5-
1 │ let x = "hello" + "what"
6-
2 │
7-
8-
This has type: string
9-
But it's being used with the + operator, which works on: int
10-
11-
Are you looking to concatenate strings? Use the operator ++, which concatenates strings.
12-
13-
Possible solutions:
14-
- Change the + operator to ++ to concatenate strings instead.
15-
16-
You can convert string to int with Belt.Int.fromString.
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11

22
We've found a bug for you!
3-
/.../fixtures/primitives1.res:2:1-2
3+
/.../fixtures/primitives1.res:2:6
44

55
1 │ /* got float, wanted int */
6-
2 │ 2. + 2
6+
2 │ 2. + 2
77
3 │
88

9-
This value has type: float
10-
But it's being used with the + operator, which works on: int
11-
12-
Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.
13-
14-
Possible solutions:
15-
- Ensure all values in this calculation has the type int. You can convert between floats and ints via Belt.Float.toInt and Belt.Int.fromFloat.
16-
- Make 2. an int by removing the dot or explicitly converting to int
9+
This has type: int
10+
But it's expected to have type: float
1711

18-
You can convert float to int with Belt.Float.toInt.
19-
If this is a literal, try a number without a trailing dot (e.g. 20).
12+
You can convert int to float with Belt.Int.toFloat.
13+
If this is a literal, try a number with a trailing dot (e.g. 20.).
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11

22
We've found a bug for you!
3-
/.../fixtures/type1.res:1:9-10
3+
/.../fixtures/type1.res:1:14
44

5-
1 │ let x = 2. + 2
5+
1 │ let x = 2. + 2
66
2 │
77

8-
This value has type: float
9-
But it's being used with the + operator, which works on: int
10-
11-
Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.
12-
13-
Possible solutions:
14-
- Ensure all values in this calculation has the type int. You can convert between floats and ints via Belt.Float.toInt and Belt.Int.fromFloat.
15-
- Make 2. an int by removing the dot or explicitly converting to int
8+
This has type: int
9+
But it's expected to have type: float
1610

17-
You can convert float to int with Belt.Float.toInt.
18-
If this is a literal, try a number without a trailing dot (e.g. 20).
11+
You can convert int to float with Belt.Int.toFloat.
12+
If this is a literal, try a number with a trailing dot (e.g. 20.).

jscomp/core/lam_convert.ml

+15
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
237237
| Pduprecord -> prim ~primitive:Pduprecord ~args loc
238238
| Plazyforce -> prim ~primitive:Plazyforce ~args loc
239239
| Praise _ -> prim ~primitive:Praise ~args loc
240+
| Pinfix _ -> assert false
240241
| Pobjcomp x -> prim ~primitive:(Pobjcomp x) ~args loc
241242
| Pobjorder -> prim ~primitive:Pobjorder ~args loc
242243
| Pobjmin -> prim ~primitive:Pobjmin ~args loc
@@ -486,6 +487,20 @@ let convert (exports : Set_ident.t) (lam : Lambda.lambda) :
486487
| Lprim (Pimport, args, loc) ->
487488
let args = Ext_list.map args (convert_aux ~dynamic_import:true) in
488489
lam_prim ~primitive:Pimport ~args loc
490+
| Lprim (Pinfix (Inf_custom(mod_, op)), args, loc) ->
491+
let fn = Lam.var (Ident.create_persistent op) in
492+
let args = Ext_list.map args (convert_aux ~dynamic_import) in
493+
let ap_info : Lam.ap_info =
494+
{
495+
ap_loc = loc;
496+
ap_status = App_na;
497+
ap_inlined = Lambda.Default_inline;
498+
}
499+
in
500+
Lam.apply fn args ap_info
501+
| Lprim (Pinfix (Inf_invariant), args, loc) ->
502+
(* TODO : invariant *)
503+
assert false
489504
| Lprim (primitive, args, loc) ->
490505
let args = Ext_list.map args (convert_aux ~dynamic_import) in
491506
lam_prim ~primitive ~args loc

jscomp/ml/lambda.ml

+6
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ type is_safe =
175175
| Safe
176176
| Unsafe
177177

178+
type infix_info =
179+
| Inf_custom of string * string
180+
| Inf_invariant
181+
178182
type primitive =
179183
| Pidentity
180184
| Pignore
@@ -199,6 +203,8 @@ type primitive =
199203
| Pccall of Primitive.description
200204
(* Exceptions *)
201205
| Praise of raise_kind
206+
(* Infix *)
207+
| Pinfix of infix_info
202208
(* object operations *)
203209
| Pobjcomp of comparison
204210
| Pobjorder

jscomp/ml/lambda.mli

+6
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ type pointer_info =
148148
| Pt_shape_none
149149
| Pt_assertfalse
150150

151+
type infix_info =
152+
| Inf_custom of string * string
153+
| Inf_invariant
154+
151155
type primitive =
152156
| Pidentity
153157
| Pignore
@@ -174,6 +178,8 @@ type primitive =
174178
| Pccall of Primitive.description
175179
(* Exceptions *)
176180
| Praise of raise_kind
181+
(* Infix *)
182+
| Pinfix of infix_info
177183
(* object primitives *)
178184
| Pobjcomp of comparison
179185
| Pobjorder

jscomp/ml/printlambda.ml

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ let primitive ppf = function
123123
| Plazyforce -> fprintf ppf "force"
124124
| Pccall p -> fprintf ppf "%s" p.prim_name
125125
| Praise k -> fprintf ppf "%s" (Lambda.raise_kind k)
126+
| Pinfix (Inf_custom(mod_, op)) -> fprintf ppf "%s.%s" mod_ op
127+
| Pinfix (Inf_invariant) -> fprintf ppf "invariant"
126128
| Pobjcomp(Ceq) -> fprintf ppf "=="
127129
| Pobjcomp(Cneq) -> fprintf ppf "!="
128130
| Pobjcomp(Clt) -> fprintf ppf "<"

0 commit comments

Comments
 (0)