-
Notifications
You must be signed in to change notification settings - Fork 448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unified operators #7057
Unified operators #7057
Changes from all commits
7205088
0005e2f
4bc812d
7551045
64d4e15
19e01b7
2c05e5a
6607973
cd7aa38
bcccd76
68fa0dc
adc65bf
efa0058
15595d2
1791379
1ef4469
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,33 @@ let transl_extension_constructor env path ext = | |
|
||
(* Translation of primitives *) | ||
|
||
(** This is ad-hoc translation for unifying specific primitive operations | ||
See [Unified_ops] module for detailed explanation. | ||
*) | ||
let translate_unified_ops (prim : Primitive.description) (env : Env.t) | ||
(lhs_type : type_expr) : Lambda.primitive option = | ||
(* lhs_type is already unified in type-level *) | ||
let entry = Hashtbl.find_opt Unified_ops.index_by_name prim.prim_name in | ||
match entry with | ||
| Some {specialization} -> ( | ||
match specialization with | ||
| {int} | ||
when is_base_type env lhs_type Predef.path_int | ||
|| maybe_pointer_type env lhs_type = Immediate -> | ||
Some int | ||
| {float = Some float} when is_base_type env lhs_type Predef.path_float -> | ||
Some float | ||
| {bigint = Some bigint} when is_base_type env lhs_type Predef.path_bigint | ||
-> | ||
Some bigint | ||
| {string = Some string} when is_base_type env lhs_type Predef.path_string | ||
-> | ||
Some string | ||
| {bool = Some bool} when is_base_type env lhs_type Predef.path_bool -> | ||
Some bool | ||
| {int} -> Some int) | ||
| _ -> None | ||
|
||
type specialized = { | ||
objcomp: Lambda.primitive; | ||
intcomp: Lambda.primitive; | ||
|
@@ -394,12 +421,21 @@ let specialize_comparison | |
raise Not_found if primitive is unknown *) | ||
|
||
let specialize_primitive p env ty (* ~has_constant_constructor *) = | ||
try | ||
let table = Hashtbl.find comparisons_table p.prim_name in | ||
match is_function_type env ty with | ||
| Some (lhs, _rhs) -> specialize_comparison table env lhs | ||
| None -> table.objcomp | ||
with Not_found -> find_primitive p.prim_name | ||
let fn_expr = is_function_type env ty in | ||
let unified = | ||
match fn_expr with | ||
| Some (lhs, _) -> translate_unified_ops p env lhs | ||
| None -> None | ||
in | ||
match unified with | ||
| Some primitive -> primitive | ||
| None -> ( | ||
try | ||
let table = Hashtbl.find comparisons_table p.prim_name in | ||
match fn_expr with | ||
| Some (lhs, _rhs) -> specialize_comparison table env lhs | ||
| None -> table.objcomp | ||
with Not_found -> find_primitive p.prim_name) | ||
|
||
(* Eta-expand a primitive *) | ||
|
||
|
@@ -458,32 +494,44 @@ let transl_primitive loc p env ty = | |
|
||
let transl_primitive_application loc prim env ty args = | ||
let prim_name = prim.prim_name in | ||
try | ||
let unified = | ||
match args with | ||
| [arg1; _] | ||
when is_base_type env arg1.exp_type Predef.path_bool | ||
&& Hashtbl.mem comparisons_table prim_name -> | ||
(Hashtbl.find comparisons_table prim_name).boolcomp | ||
| _ -> | ||
let has_constant_constructor = | ||
match args with | ||
| [_; {exp_desc = Texp_construct (_, {cstr_tag = Cstr_constant _}, _)}] | ||
| [{exp_desc = Texp_construct (_, {cstr_tag = Cstr_constant _}, _)}; _] | ||
| [_; {exp_desc = Texp_variant (_, None)}] | ||
| [{exp_desc = Texp_variant (_, None)}; _] -> | ||
true | ||
| _ -> false | ||
in | ||
if has_constant_constructor then | ||
match Hashtbl.find_opt comparisons_table prim_name with | ||
| Some table when table.simplify_constant_constructor -> table.intcomp | ||
| Some _ | None -> specialize_primitive prim env ty | ||
(* ~has_constant_constructor*) | ||
else specialize_primitive prim env ty | ||
with Not_found -> | ||
if String.length prim_name > 0 && prim_name.[0] = '%' then | ||
raise (Error (loc, Unknown_builtin_primitive prim_name)); | ||
Pccall prim | ||
| [arg1] | [arg1; _] -> translate_unified_ops prim env arg1.exp_type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a couple of unary primitive to support, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I noticed all the other functions don't have unaries, so if they're planned for this PR great.
This comment was marked as resolved.
Sorry, something went wrong. |
||
| _ -> None | ||
in | ||
match unified with | ||
| Some primitive -> primitive | ||
| None -> ( | ||
try | ||
match args with | ||
| [arg1; _] | ||
when is_base_type env arg1.exp_type Predef.path_bool | ||
&& Hashtbl.mem comparisons_table prim_name -> | ||
(Hashtbl.find comparisons_table prim_name).boolcomp | ||
| _ -> | ||
let has_constant_constructor = | ||
match args with | ||
| [ | ||
_; {exp_desc = Texp_construct (_, {cstr_tag = Cstr_constant _}, _)}; | ||
] | ||
| [ | ||
{exp_desc = Texp_construct (_, {cstr_tag = Cstr_constant _}, _)}; _; | ||
] | ||
| [_; {exp_desc = Texp_variant (_, None)}] | ||
| [{exp_desc = Texp_variant (_, None)}; _] -> | ||
true | ||
| _ -> false | ||
in | ||
if has_constant_constructor then | ||
match Hashtbl.find_opt comparisons_table prim_name with | ||
| Some table when table.simplify_constant_constructor -> table.intcomp | ||
| Some _ | None -> specialize_primitive prim env ty | ||
(* ~has_constant_constructor*) | ||
else specialize_primitive prim env ty | ||
with Not_found -> | ||
if String.length prim_name > 0 && prim_name.[0] = '%' then | ||
raise (Error (loc, Unknown_builtin_primitive prim_name)); | ||
Pccall prim) | ||
|
||
(* To propagate structured constants *) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if the
when
clause in this case is complete. But I guess this case is just unnecessary and can be removes as it is already expressed as the last default case?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This always takes precedence int over other types. (Rule 1-2) The last default case is a fallback strategy. (Rule 3)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give an example of any change after removing this first case?
All the other cases seem to have incompatible when clauses, so it would fall back to the last case no matter what.
Unless I'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. There is no logical difference in the behavior after removing that case. I was just thinking of the computational difference. In the existing codebase, I assume the first case is hit the most frequently (since it was originally int-only).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just a detail anyway. Not much difference. Whatever you think is best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it probably doesn't matter, but I'll leave it as is because it seems easier to understand the intent.