-
Notifications
You must be signed in to change notification settings - Fork 15
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
Expose control flow as an API #145
Comments
I'm subtly and dangerously wrong above. A It may seem a bit silly to provide
Doing it this way would require slightly more than a We could rewrite the runtime code so that it calls into the same handler during normal loop control flow. In the fullness of time, we might even be able to provide the loops themselves as statement macros, using the same API from with 007. |
Note that, even if we make the feature totally static and lexical, we will still have interaction between
And, since the call stack is dynamic and subs are first-class, this could also happen:
|
Coming back to this issue and re-reading it, I say we might consider going the Python route and forbidding Yes, that's a sad cop-out, I know. But (a) since Python does this, it's within 007's rights to choose that route too, and (b) having the conservative version of the feature early is more useful than not having the ambitious version of the feature for a long time, and (c) seeing the feature implemented in a more static way might make us realize things we otherwise would not. |
This issue is bounded above in an interesting way by #166 and similar. When we compile to a different backend, we can no longer do very exotic things with the control flow. And since we want to have other backends, 007 also needs to be non-exotic enough so that code can be generated that corresponds to everything the control flow API can do. |
But (as I come back to this later and re-read it) this should be perfectly fine considering what we want to do. It simply means that all the control flow we want to be able to generate needs to be translatable down into conditionals and loops, possibly on gensym'd boolean variables. My intuition tells me this is true of Note, however, that it's not obviously true of the |
Been thinking lately about how I have a feeling this could be expressed/designed very neatly in terms of basic blocks. Just need to find the time to sit down and do so. |
Quite a bit of overlap here with #252 which I just filed. |
When I re-read this issue, I feel what's missing from the OP is that control flow is an aspect of code generation. (That's also why I just closed #252.) Getting down to brass tacks instead of trying to explain in an abstract manner, here's what I imagine a code generation API might look like:
|
Note that even the conservatism suggested in #145 (comment) is not going to suffice. Why? Because blocks with parameters code-generate as separate "units" of callable code in the general case, because that's the only way closures inside of them can work. I didn't realize this until I started thinking about bytecode and trying to transcribe our example programs into bytecode. I'm still mulling on it all, but I think this pushes us towards treating We're still free to lock it down into being syntactically lexical, but (again, from what I can see so far) there would be no simplification in semantics in the general case from doing so. |
Just driving by to point out that |
I was reminded of this phrase ("The compiler could intercept them") as I read Dan Abramov's React as a UI Runtime, especially the section about Inversion of Control. To wit,
It seems to me we want the same sort of layer for |
After several years of waiting for the other shoe to drop, I now think that the control API should be phrased in terms of continuations. Hoping to be able to flesh that out in a concrete way soon, but basically:
Again, this is but a rough sketch of the idea. Continuations will generally be compiled away into weaker constructs when at all possible. Either we rule out the remaining cases (which was basically the idea with forbidding loop jumps through function boundaries, Python-style), or we accept that continuations do exist sometimes, and basically base our runtime architecture on them. I'm not in a rush to do the latter, but I also think it wouldn't be so bad. Basically Alma could run on a CESK machine. |
Maybe I'm not really contradicting 2021-me when I say that it feels like we're essentially talking about algebraic effects here. Maybe the connection is this: if you have continuations and a CESK machine, then algebraic effects can be phrased in terms of having a bit more access to the machine itself, especially the K part. |
I would like to be able to provide
next
,last
, andredo
in loops as statement macros. But I would also like the underlying mechanism that they lean upon to be exposed as a clean API.What would the API look like? Something like this:
for
andwhile
loops would register their loopQ::Block
in some way with the tagloop
.ctrlflow.goto(location)
.next
would then beif loopcondition { ctrlflow.goto(findtag("loop").beginning); } else { ctrlflow.goto(findtag("loop").end); }
last
would bectrlflow.goto(findtag("loop").end);
redo
would bectrlflow.goto(findtag("loop").beginning);
I think we don't need to make this mechanism dynamic (like in Perl 6) — in fact, it's easier to statically check if we don't. Which also means that
.map
won't be considered a loop in the above sense. On the other hand, if someone wanted to write a custom loop, they'd simply provide it with the tagloop
, and it'd play along.The text was updated successfully, but these errors were encountered: