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
enable lambda-lifting for the JavaScript target #586
Conversation
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 is awesome, good to merge! 🚀
I thought of two follow-ups. I'll start on the first one ~tomorrow and see about the second one based on the outcome:
- have as much of
tests/lang_callable/iter
run for js/all platforms see where things land - quick update of the manual to remove the "big" mentions of can't use closure iterators for JS (rest can be long tail)
Summary ======= Previously, inner closure procedures were not lifted into free-standing procedures during `transf`, but rather kept as is and mapped to nested JavaScript functions by `jsgen`. Besides requiring the JavaScript target to be special-cased in `transf` and `lambdalifting`, this also caused observable semantic issues: the destructors for captured variables were called when leaving the scope in which they were defined, not when the closure got destroyed. In order to bring the closure semantics in line with the other targets and as a prerequisite for full ORC support, lambda-lifting is now also enabled when using the JS target -- the code generator is adjusted to support the lifted procedures. The code generator changes are also a preparation for full closure iterator support. As a side-effect, closures now also work as expected when using the JS target and executing non-compile-time-only procedures that have inner closure procedures at compile-time. Details ======= - remove the dispatching based on the selected backend from `transf` and `lambdalifting` - remove all code related to the previous closure support from `jsgen` - implement support for lifted procedures in `jsgen` The hidden environment parameter of routines using the `.closure` calling convention is mapped to the this parameter at the JavaScript level. When a NimSkull closure object is created, a new function instance is created via `bind` and the provided environment bound to the `this` parameter. In addition, the both the function and environment are also assigned to the respective prc and env properties on the function object -- this allows for later retrieval. Compared to using an object, this approach has the benefit that closures can still be passed to an imported procedure that expects a JavaScript function object, without requiring any changes to the user code.
62a750d
to
3de5e7f
Compare
Yep, that's a good idea. Having the |
bors r+ |
Build succeeded: |
Summary
Previously, inner closure procedures were not lifted into free-standing procedures during
transf
, but rather kept as-is and mapped to nested JavaScript functions byjsgen
. Besides requiring the JavaScript target to be special-cased intransf
andlambdalifting
, this also caused observable semantic issues: the destructors for captured variables were called when leaving the scope in which they were defined, not when the closure got destroyed.In order to bring the closure semantics in line with the other targets and as a prerequisite for full ORC support, lambda-lifting is now also enabled when using the JS target -- the code generator is adjusted to support the lifted procedures. The code generator changes are also a
preparation for full closure iterator support.
As a side-effect, closures now also work as expected when using the JS target and executing non-compile-time-only procedures that have inner closure procedures at compile-time.
Details
transf
andlambdalifting
jsgen
jsgen
The hidden environment parameter of routines using the
.closure
calling convention is mapped to thethis
parameter at the JavaScript level.When a NimSkull closure object is created, a new function instance is created via
bind
and the provided environment bound to thethis
parameter. In addition, the both the function and environment are also assigned to the respectiveprc
andenv
properties on the function object -- this allows for later retrieval.Compared to using an object, this approach has the benefit that closures can still be passed to an imported procedure that expects a JavaScript function object, without requiring any changes to the user code.
Notes for Reviewers