-
Notifications
You must be signed in to change notification settings - Fork 453
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
201 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,93 @@ | ||
open Btype | ||
open Types | ||
open Misc | ||
|
||
(* | ||
Unified_ops is for specialization of some primitive operators. | ||
For example adding two values. We have `+` for ints, `+.` for floats, and `++` for strings. | ||
That because we don't use implicit type conversion or overloading. | ||
That because we don't allow implicit conversion or overloading for operations. | ||
It is a fundamental property of the ReScript language, but at the same time it is far from the best DX we can think of, and it became a problem when introducing new primitives like bigint. | ||
It is a fundamental property of the ReScript language, but it is far from the best DX we can think of, | ||
and it became a problem when new primitives like bigint were introduced. | ||
See discussion: https://github.com/rescript-lang/rescript-compiler/issues/6525 | ||
1. Type level translation | ||
Unified ops mitigate the problem by adding ad-hoc translation rules on applications of the core built-in operators | ||
which have form of binary infix ('a -> 'a -> 'a) or unary ('a -> 'a) | ||
2. IR level translation | ||
*) | ||
Translation rules should be applied in its application, in both type-level and IR(lambda)-level. | ||
type args = (Asttypes.arg_label * Parsetree.expression) list | ||
type targs = (Asttypes.arg_label * Typedtree.expression option) list | ||
The rules: | ||
type specialized_type = { | ||
int: Path.t; | ||
bool: Path.t option; | ||
float: Path.t option; | ||
bigint: Path.t option; | ||
string: Path.t option; | ||
} | ||
1. If the lhs type is a primitive type, unify the rhs and the result type to the lhs type. | ||
2. If the lhs type is not a primitive type but the rhs type is, unify lhs and the result type to the rhs type. | ||
3. If both lhs type and rhs type is not a primitive type, unify the whole types to the int. | ||
Since these are simple ad-hoc translations for primitive applications, we cannot use the result type defined in other contexts. | ||
So falling back to int type is the simplest behavior that ensures backwards compatibility. | ||
*) | ||
|
||
let specialized_types = create_hashtable [||] | ||
type form = Unary | Binary | ||
|
||
type specialized_primitive = { | ||
type specialization = { | ||
int: Lambda.primitive; | ||
bool: Lambda.primitive option; | ||
float: Lambda.primitive option; | ||
bigint: Lambda.primitive option; | ||
string: Lambda.primitive option; | ||
} | ||
|
||
let translate_type_application (env : Env.t) (funct : Parsetree.expression) | ||
(args : args) : (targs * type_expr) option = | ||
None | ||
type entry = { | ||
path: string; | ||
(** TODO: Maybe it can be a Path.t in Predef instead of string *) | ||
name: string; | ||
form: form; | ||
specialization: specialization; | ||
} | ||
|
||
let builtin x = Primitive_modules.pervasives ^ "." ^ x | ||
|
||
let entries = | ||
[| | ||
{ | ||
path = builtin "+"; | ||
name = "%add"; | ||
form = Binary; | ||
specialization = | ||
{ | ||
int = Paddint; | ||
bool = None; | ||
float = Some Paddfloat; | ||
bigint = Some Paddbigint; | ||
string = Some Pstringadd; | ||
}; | ||
}; | ||
{ | ||
path = builtin "-"; | ||
name = "%sub"; | ||
form = Binary; | ||
specialization = | ||
{ | ||
int = Psubint; | ||
bool = None; | ||
float = Some Psubfloat; | ||
bigint = Some Psubbigint; | ||
string = None; | ||
}; | ||
}; | ||
|] | ||
|
||
let translate_primitive_application (env : Env.t) (prim : Primitive.description) | ||
(args : args) : Lambda.primitive option = | ||
None | ||
let index_by_path = | ||
entries |> Array.map (fun entry -> (entry.path, entry)) |> create_hashtable | ||
|
||
let index_by_name = | ||
entries |> Array.map (fun entry -> (entry.name, entry)) |> create_hashtable | ||
|
||
(* | ||
Actual implementations of translation are colocated into core modules | ||
You can find it in: | ||
- Type-level : ml/typecore.ml | ||
- IR-level : ml/translcore.ml | ||
With function name "translate_unified_application" | ||
*) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
type form = Unary | Binary | ||
|
||
type specialization = { | ||
int: Lambda.primitive; | ||
bool: Lambda.primitive option; | ||
float: Lambda.primitive option; | ||
bigint: Lambda.primitive option; | ||
string: Lambda.primitive option; | ||
} | ||
|
||
type entry = { | ||
path: string; | ||
name: string; | ||
form: form; | ||
specialization: specialization; | ||
} | ||
|
||
val index_by_path : (string, entry) Hashtbl.t | ||
|
||
val index_by_name : (string, entry) Hashtbl.t |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters