We'll leverage slices. We track a single LOCALS pointing to the current slice for locals.
'LOCALS' variable
'( - )\nVariable; holds a pointer to the current set of local variables' 'LOCALS' describe
Functions will get wrapped in a localize combinator. This needs to save and restore the prior LOCALS. dip makes this easy:
[ &LOCALS @ [ memory.request &LOCALS ! invoke &LOCALS @ memory.release ] dip &LOCALS ! ] 'localize' define
'( quote - )\nProvide a private **LOCALS** slice for a quote\n' 'localize' describe
Locals can be accessed via simple functions:
[ [ &LOCALS @ ] dip memory.fetch ] 'local.at' define
'( value number:offset - )\nStore value into local' 'local.at' describe
[ [ &LOCALS @ ] dip memory.store ] 'local.store:at' define
'( number:offset - value )\nFetch a value stored in a local' 'local.store:at' describe
[ [ #0 local.store:at #0 local.at #0 local.at * ] localize ] 'square' define
[ [ #0 local.store:at #2 square #0 local.at * ] localize ] 'test' define
#100 test