-
Notifications
You must be signed in to change notification settings - Fork 7
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
Level tracking & bindings in escapes #2
Comments
Number #1 is a bug, specifically this bug. Number #2 is a feature, although a debatably useful one. It's not documented and I'm not set on keeping it forever, but I'm curious to play with it a bit. The idea is that future-stage bound variables are in scope in the present, but a future variable of type |
Let me check whether I understand the design. Is the idea that the scope should be normal OCaml scope (so that every variable refers to the closest enclosing binding, ignoring quotations/escapes for scoping purposes)? The undocumented feature you describe sounds like it can be emulated by inserting a [%code fun x -> [%e exp]] behaves like this MetaOCaml code: .< fun x -> .~(let x = .<x>. in exp) >. [Edit: the translation into MetaOCaml should be a little more elaborate to ensure that |
Yes to both: the scope should be the normal OCaml scope, and inserting lets in MetaOCaml has the same effects as this feature in |
(Thanks for this very exciting ppx-extension!)
Binding analysis doesn't keep track of levels or track bindings in escapes, which leads to some surprising behaviour. Here are some examples:
Shadowing a quoted binding in an escaped expression:
The following code is rejected
with the following error:
I can imagine a design where this is acceptable, in which only bindings from quotations are in scope within quotations. It's different from MetaOCaml, where both
x
andy
are in scope in the body of thelet
, and where the equivalent expression would build code for a function that returns a future-stagee
via cross-stage persistence.However, that design not quite what's going on here, as the following example shows. The following code is accepted
and produces the code value
fun x -> 3
The fact that second example is accepted while the first is rejected illustrates that only the environment of quotation-bound variables is considered when checking free variables in the subexpression
[%code x]
. However, the generated code illustrates that the escape-bound variable actually shadows the quotation-bound variable during execution. The treatment of binding in the two situations is not consistent.Using a quoted binding in an escaped expression:
All of the following expressions produce code for the identity function, which is rather surprising:
In MetaOCaml
x
is a future-stage binding, so it can't be used in the present; only the first and third examples are allowed. (Perhaps the design in whichx
can appear either escaped or quoted works out, but it seems a bit less uniform and extensible.)Possible solution
Here's one way to fix the problems above:
Keep track of the level of each expression (i.e. whether it appears inside or outside a quotation), and the level of each bound variable.
Analyse both quoted and escaped expressions, keeping track of variables bound at both stages, and their levels.
Enforce the following rules:
Let me know if a pull request would be of interest!
The text was updated successfully, but these errors were encountered: