Organise and simplify translation of primitives#1557
Conversation
|
I am unsure whether it should be done in this PR, but some cases of |
| | Send_cache, [obj; meth; cache; pos] -> | ||
| Lsend(Cached, meth, obj, [cache; pos], loc) | ||
| | Send_cache, _ -> | ||
| raise(Error(loc, Wrong_arity_builtin_primitive prim_name)) |
There was a problem hiding this comment.
Could this case be regrouped in one | (... | Loc | Send | Send_self | Send_cache ), _ -> , otherwise I think the user wonder what is the difference between all these lines.
| (**************************************************************************) | ||
|
|
||
| (* Translation of primitives *) | ||
|
|
There was a problem hiding this comment.
Could you add some guide of how to add a new primitive? Something simple perhaps like:
add your primitive to
primor one of the sub-datatype, then toprimitives_table, finally let the typer guide you to the missing cases.
There was a problem hiding this comment.
I decided against adding a comment. I don't think it makes adding a new primitive noticeably easier and these kinds of comments tend not to get updated when things change, leaving things in a worse state than if they weren't there.
|
|
||
| exception Error of Location.t * error | ||
|
|
||
| (* Insertion of debugging events *) |
There was a problem hiding this comment.
It is not clear when and where to add debugging events, could you point to the documentation?
There was a problem hiding this comment.
I don't think there is documentation, nor do I know the rules and invariants. I tried simplifying things when writing this patch, but it made some tests around backtraces fail, so instead I was just careful to keep the behaviour the same.
|
@damiendoligez, can we consider this one for 4.07 or at least merge #1465 |
|
@damiendoligez, @lpw25, can we have this PR in 4.07 ? |
|
I have been studying this PR and will post a review at some point today. |
nojb
left a comment
There was a problem hiding this comment.
I reviewed this PR.
I think it is a great improvement on the current state of affairs. I read the code carefully and am confident it is correct (modulo a small issue with the handling of the raise primitive). More importantly, I am confident that if there is a bug, it will be easy to find and fix thanks to the new code organization. This is in contrast with the current state of affairs where the handling of primitives is spread all over the place and many invariants are not tracked by the type system.
Some remarks about the code itself.
While the diff is large, a lot of it is due to moving code around and "type-directed" refactoring.
Conceptually, the PR does several things:
- merge the code used by
transl_primitive(which eta-expands a primitive) andtransl_primitive_application(which translates a fully applied primitive). This cuts down on a lot of duplicated code, and fixes at least MPR#7674 and MPR#7666. - A more robust function to lookup primitives
lookup_primitiveinstead offind_primitive. This would have produced a sensible error message for MPR#7666. - Clean up the insertion of debug events in the generated lambda code (functions
wrapandwrap0). The current code here is so convoluted that it took me some time to convince myself that the new code (which is simpler) is actually equivalent. - Introduce a new type
Translprim.primwhich includes the usualLambda.primitivebut also other primitives that do not currently have a representation in the type system and are only recognized by their names. The "new" primitives are: comparison primitives,send,sendself,sendcache, andraise_with_backtrace. Having constructors corresponding to these primitives allows to use pattern matching and, in the case of comparisons, to handle them before specialization. - Some primitives that need special handling are lifted out of the
Lambda.primitivetype into the newTranslprim.primtype. On the one hand pattern matching makes it obvious where special handling is needed. On the other hand, it also makes it clear that these primitives do not survive lambda-generation. The primitives affected are:raise,lazyforce, andloc_*primitives.
In an ideal world, having the PR split into smaller commits would make it easier to digest, but personally I don't feel it is reason enough to delay its integration.
bytecomp/translprim.ml
Outdated
| | Compare, Compare_int32s -> Pccall caml_int32_compare | ||
| | Compare, Compare_int64s -> Pccall caml_int64_compare | ||
|
|
||
| let lamda_of_loc kind loc = |
| let prim = lookup_primitive loc p env path in | ||
| let has_constant_constructor = false in | ||
| let prim = | ||
| match specialize_primitive env ty ~has_constant_constructor prim with |
There was a problem hiding this comment.
Why not have specialize_primitive return prim instead of prim option?
bytecomp/translprim.ml
Outdated
| | Raise_regular, Lvar argv when Hashtbl.mem try_ids argv -> | ||
| Raise_reraise | ||
| | _, _ -> | ||
| Raise_regular |
There was a problem hiding this comment.
Should probably be kind instead of Raise_regular, to avoid changing Raise_notrace case.
|
I've rebased, addressed comments and added a changes entry. |
|
The CI failure is unrelated to this patch (and has now been fixed on trunk). |
|
Inria's CI fails on ARM. Is this just a matter of running make alldepend? |
|
I ran
in the commits, so this is a surprising error. |
|
Ah, there is aparently now a |
|
Leo White (2018/04/09 13:46 +0000):
Ah, there is aparently now a `ocamldoc/stdlib_non_prefixed/.depend`
file that also needs updating, and gets updated by `make alldepend`.
Mark has pushed the fix to trunk.
Thanks guys!
|
|
Thanks |
Currently the translation of builtin
externals in bytecomp is pretty disorganized. It is handled across multiple parts oftranslcore.mland different builtins are handled in different places. This has lead to a number of silly little bugs, e.g. this one or this bug that is still on trunk:This PR tries to improve the situation. It moves all the handling for primitives into a new
translprim.mlfile, and uses an internal type:to represent the various builtin
externals. The cases other thanPrimitiveare the ones that require special handling. These have previously been handled in different ad-hoc ways but here are handled by a fairly uniform set of functions intranslprim.ml.