Skip to content

Commit

Permalink
PoC: generic infix operators
Browse files Browse the repository at this point in the history
  • Loading branch information
cometkim committed Sep 28, 2024
1 parent 6d78c58 commit 7d0dcee
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@
3 │ let x = num + 12.
4 │

This value has type: float
But it's being used with the + operator, which works on: int

Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.

Possible solutions:
- 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.
- Make 12. an int by removing the dot or explicitly converting to int
This has type: float
But it's expected to have type: int

You can convert float to int with Belt.Float.toInt.
If this is a literal, try a number without a trailing dot (e.g. 20).
Original file line number Diff line number Diff line change
@@ -1,20 +0,0 @@

We've found a bug for you!
/.../fixtures/math_operator_int.res:3:9-11

1 │ let num = 0.
2 │
3 │ let x = num + 12.
4 │

This has type: float
But it's being used with the + operator, which works on: int

Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.

Possible solutions:
- 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.
- Change the operator to +., which works on float

You can convert float to int with Belt.Float.toInt.
If this is a literal, try a number without a trailing dot (e.g. 20).
Original file line number Diff line number Diff line change
@@ -1,16 +0,0 @@

We've found a bug for you!
/.../fixtures/math_operator_string.res:1:9-15

1 │ let x = "hello" + "what"
2 │

This has type: string
But it's being used with the + operator, which works on: int

Are you looking to concatenate strings? Use the operator ++, which concatenates strings.

Possible solutions:
- Change the + operator to ++ to concatenate strings instead.

You can convert string to int with Belt.Int.fromString.
18 changes: 6 additions & 12 deletions jscomp/build_tests/super_errors/expected/primitives1.res.expected
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@

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

1 │ /* got float, wanted int */
2 │ 2. + 2
2 │ 2. + 2
3 │

This value has type: float
But it's being used with the + operator, which works on: int

Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.

Possible solutions:
- 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.
- Make 2. an int by removing the dot or explicitly converting to int
This has type: int
But it's expected to have type: float

You can convert float to int with Belt.Float.toInt.
If this is a literal, try a number without a trailing dot (e.g. 20).
You can convert int to float with Belt.Int.toFloat.
If this is a literal, try a number with a trailing dot (e.g. 20.).
18 changes: 6 additions & 12 deletions jscomp/build_tests/super_errors/expected/type1.res.expected
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@

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

1 │ let x = 2. + 2
1 │ let x = 2. + 2
2 │

This value has type: float
But it's being used with the + operator, which works on: int

Floats and ints have their own mathematical operators. This means you cannot add a float and an int without converting between the two.

Possible solutions:
- 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.
- Make 2. an int by removing the dot or explicitly converting to int
This has type: int
But it's expected to have type: float

You can convert float to int with Belt.Float.toInt.
If this is a literal, try a number without a trailing dot (e.g. 20).
You can convert int to float with Belt.Int.toFloat.
If this is a literal, try a number with a trailing dot (e.g. 20.).
15 changes: 15 additions & 0 deletions jscomp/core/lam_convert.ml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
| Pduprecord -> prim ~primitive:Pduprecord ~args loc
| Plazyforce -> prim ~primitive:Plazyforce ~args loc
| Praise _ -> prim ~primitive:Praise ~args loc
| Pinfix _ -> assert false
| Pobjcomp x -> prim ~primitive:(Pobjcomp x) ~args loc
| Pobjorder -> prim ~primitive:Pobjorder ~args loc
| Pobjmin -> prim ~primitive:Pobjmin ~args loc
Expand Down Expand Up @@ -486,6 +487,20 @@ let convert (exports : Set_ident.t) (lam : Lambda.lambda) :
| Lprim (Pimport, args, loc) ->
let args = Ext_list.map args (convert_aux ~dynamic_import:true) in
lam_prim ~primitive:Pimport ~args loc
| Lprim (Pinfix (Inf_custom(mod_, op)), args, loc) ->
let fn = Lam.var (Ident.create_persistent op) in
let args = Ext_list.map args (convert_aux ~dynamic_import) in
let ap_info : Lam.ap_info =
{
ap_loc = loc;
ap_status = App_na;
ap_inlined = Lambda.Default_inline;
}
in
Lam.apply fn args ap_info
| Lprim (Pinfix (Inf_invariant), args, loc) ->
(* TODO : invariant *)
assert false
| Lprim (primitive, args, loc) ->
let args = Ext_list.map args (convert_aux ~dynamic_import) in
lam_prim ~primitive ~args loc
Expand Down
6 changes: 6 additions & 0 deletions jscomp/ml/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ type is_safe =
| Safe
| Unsafe

type infix_info =
| Inf_custom of string * string
| Inf_invariant

type primitive =
| Pidentity
| Pignore
Expand All @@ -199,6 +203,8 @@ type primitive =
| Pccall of Primitive.description
(* Exceptions *)
| Praise of raise_kind
(* Infix *)
| Pinfix of infix_info
(* object operations *)
| Pobjcomp of comparison
| Pobjorder
Expand Down
6 changes: 6 additions & 0 deletions jscomp/ml/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ type pointer_info =
| Pt_shape_none
| Pt_assertfalse

type infix_info =
| Inf_custom of string * string
| Inf_invariant

type primitive =
| Pidentity
| Pignore
Expand All @@ -174,6 +178,8 @@ type primitive =
| Pccall of Primitive.description
(* Exceptions *)
| Praise of raise_kind
(* Infix *)
| Pinfix of infix_info
(* object primitives *)
| Pobjcomp of comparison
| Pobjorder
Expand Down
2 changes: 2 additions & 0 deletions jscomp/ml/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ let primitive ppf = function
| Plazyforce -> fprintf ppf "force"
| Pccall p -> fprintf ppf "%s" p.prim_name
| Praise k -> fprintf ppf "%s" (Lambda.raise_kind k)
| Pinfix (Inf_custom(mod_, op)) -> fprintf ppf "%s.%s" mod_ op
| Pinfix (Inf_invariant) -> fprintf ppf "invariant"
| Pobjcomp(Ceq) -> fprintf ppf "=="
| Pobjcomp(Cneq) -> fprintf ppf "!="
| Pobjcomp(Clt) -> fprintf ppf "<"
Expand Down
Loading

0 comments on commit 7d0dcee

Please sign in to comment.