feat: recursive local variables
The lack of recursion in goboscript (only tail recursion) reduces the flexibility and power of functions/procs in gs. This is because local vars do not belong to a specific 'frame' or 'level' of the function. This post provides a simple concept for how local variables could work (efficiently) in gs.
[!NOTE] Recursive local vars should only be allowed with warped (not nowarp) procs and funcs, because otherwise there could be memory conflicts
Syntax
example syntax (each local var is explicitly made into a recursive local var):
func foo(a) {
rloc c = ...;
...
}
or (function is assigned as recursive, so all local variables are also recursive):
recur func foo(a) {
local c = ...;
...
}
concept
-
For each recursive local variable, make a list (it also has to be local to the function.) e.g. In this case,
rloc ccould generate a list called:foo: c(note this would conflict with local lists but that is a rejected feature) -
At the start of the func or proc, add an empty item to each list
Note that this *could* be optimised to only add to the list when the variable is first assigned, but then checks for recursion and possibilities of not being initialised (e.g. in an if statement). But this does not matter because if you are using recursive local vars, one shouldn't expect it to be that micro-optimised anyway -
access the rloc variables using the 'last' item of list (using 'last' instead of item[length list] would reduce block count and improve efficiency in vanilla scratch):
-
At the end of the proc, delete the last item of each of the rloc lists. This may happen just before a
stop_this_scriptblock, or just before thestop_this_scriptblock in thereturnkeyword's codegen, or just when a proc ends naturally
things that would have to be handled differently (kind of obvious)
-
c = "string";-> -
c += 12;-> -
say c;->
IIRC, "replace item X of Y with Z" is really slow. I could be wrong. What if the variable needs to be a list?
- it's not slow - what is slow is list insertion - hence the use of item last of list rather than item 1 of list and using an insertion
- goboscript doesnt have local lists.
if you want to make sure these will never conflict with local lists, were they to be implemented, just add a prefix
'rloc 'inside of the list name, e.g.foo: rloc c
recursion should be detected and all local variables should be made into recursive variables instead of adding a new keyword and scope
that means you would have to check for indirect recursion as well, e.g. foo calls bar, and bar calls foo, except for some certain condition
im already doing that, to detect unused functions