💾 Archived View for bbs.geminispace.org › s › FORTH › 5266 captured on 2024-03-21 at 18:22:33. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-02-05)
-=-=-=-=-=-=-
I'm trying out lambdas in nforth. The syntax is simple and I have some good use cases for lambdas.
Syntactically, to create a lambda, just surround some code with curly braces:
[ { ". Hello world" } dup eval eval ]
The square braces here ensure that the entire thing gets compiled prior to execution.
When nforth processes it, the address of the lambda is left on the datastack. This address can be evaluated using the `eval` word (lambda--) which takes the lambda address off the datastack and runs it. Execution then continues.
Once created, a lambda may be passed around to be executed at a later time, used as a callback, or used to order program flow, such as conditionals or loops.
Internally, lambdas are a bit complicated. Since we don't want to execute the lambda code right away, we need to compile a jump over the lambda (but we don't know its size yet!). We also need to compile code that will stack the lambda address. We need to compile the lambda, compile the <return> token, and fixup the jump (now that we do know the size.
Here is my implementation of `{`
\ lambdas are compiled blocks of code, to be passed around \ <lit><lambda-address><branch><over-lambda>...lambda...<NEXT>|<--- \ (--lambda-address) : { [ \ (--lambda) ' ['] , HERE@ 12 + , \ compile <lit><lambda-address>, 3 tokens ahead ' branch , HERE@ zero , \ <branch> <0> over the lambda, --fixup $F80C48A8 COMPILE.UNTIL \ compile to end of lambda ' ; , \ terminate with <RETURN> HERE@ swap ! \ fixup branch ; ] IMMEDIATE
$F80C48A8 is the FNV1a hash of the '}' terminator string.
God, I love forth, times like these.
https://tildegit.org/stack/nforth
2023-09-12 · 6 months ago