When I was designing the context sensitivity functions in the API, I wondered if this should work:
rebElide("let x: 1000");
assert(1020 = rebUnboxInteger("x + 20"));
Under the hood, what's happening here is:
rebElideHelper(LIBREBOL_BINDING(), "let x: 1000", rebEND);
assert(1020 = rebUnboxIntegerHelper(LIBREBOL_BINDING(), "x + 20", rebEND));
And that LIBREBOL_BINDING() is something that you can configure to be any context... with the big trick being that inside of a native, it uses a shadowed variable that's an argument to the native... allowing the context to be "inside" the function for API calls in the native body.
With that being a fixed context pointer, it can't be updated. Each call would be independent and see the same environment coming in. So no accrual.
But what if LIBREBOL_BINDING() wasn't a pointer to a context, but a pointer-to-a-pointer to a context? Each API call could potentially update that. The environment could grow with each call.
It's Technically Questionable
Right now the LIBREBOL_CONTEXT() is defined to things that should not be changed. e.g. the level_
parameter to a native cannot change, because it's used by other macros.
So there'd have to be a copy of it made that could be changed:
Bounce N_whatever(Level* const level_) {
Context* librebol_binding = level_; // capture this, not level_
...
}
So this is suggesting that librebol_binding
variable would get updated as each API got called, taking the binding enviroment as it was outgoing from the last call.
Another technical aspect is that these new environments being handed out as pointer-to-pointer don't have anything keeping them alive in the GC. They're stray pointers inside the user's code.
Does It Even Make Sense?
It wouldn't know anything about the scoping rules of the C it's running inside:
if (condition) {
rebElide("let inside-if: 304");
}
rebElide("print [-{Should we be seeing}- inside-if]");
I think this is likely to just invite bugs and lead to leaks. If you want to use a LET and not leak it, you'd have to put your evaluations in parentheses:
rebElide("(let x: -{lame and easy to forget}- ...)");
The desire of being able to do multiple evaluations inside a context that accrues context is valid, but given that something needs to be keeping those contexts alive then it should be done through an API.