Change the mainloop so that words are executed immediately after they're read.
This greatly simplifies execution model and allow the "DEFINE" word to become
an IMMEDIATE and stop its "copy from compiled words" scheme.
The downside to this is that flow control words no longer work when being used
directly in the input buffer. They only work as part of a definition.
It also broke "RECURSE", but I've replaced it with "BEGIN" and "AGAIN".
Another effect of this change is that definitions can now span multiple lines.
All in all, it feels good to get rid of that COMPBUF...
Readline, instead of being triggered by the end of execution of the last
compiled line is now triggered "just in time", by "WORD".
This allows IMMEDIATE words reading input buffer to span multiple lines
( comments for example, but colon definitions will soon follow ).
Add words "COMPILE" and "DROP". The goal is to soon make "DEFINE" immediate
and have it compile from input directly. This whole "main loop compiles
everything and DEFINE picks up compiled atoms" is a bit messy.
This will allow us to support backward branching with just one new (bbr) word.
Also, this allow us to have "(" word sooned in core.fth and thus allow for
earlier commenting.
My approach with RS was slightly wrong: RS' TOP was always containing current
IP. It worked, but it was problematic when came the time to introduce
RS-modifying words: it's impossible to modify RS in a word without immediately
messing your flow.
Therefore, what used to be RS' TOS has to be a variable that isn't changed
midway by RS-modifying words. I guess that's why RS is called *return* stack...
Big one.
This allows us to write higher order words directly in Forth, which is much
more convenient than writing post-immediate (see "NOT" structure in diff if
you want to see what I mean) structures in ASM.
These structures can then be written to ROM (rather than loaded in RAM for
definitions loaded at run-time).
That's quite a bit of tooling that was added, 2 compilations stages, but I
think it's well worth it.
Things are better now, but immediates inside colons are broken. However,
IF/THEN/ELSE are now immediates and it's much cleaner this way. Still, this
commit has too much stuff in it, I need to commit, I don't want to lose this
step.
The goal was to be able to implement "(" in forth, but I realised that my
INTERPRET approach was wrong. Compiling the line beforehand is, after all,
not good. I'll have to change it again.
Previous approach was broken with regards to defined word using CREATE.
Also, reduce name length by one to make space for a new flags field for
"immediate" (which isn't used yet).
This scheme of "when we handle line-by-line, compile one word at a time then
execute" so that we could allow words like "CREATE" to call "readword" before
continuing was a bad scheme. It made things like branching outside of a colon
definition impossible.
This commit implement a new "litWord". When an undefined word is encountered at
compile time, it is included as-is in a string literal word. It is at run time
that we decide what to do with it.
Not much of a gain in terms of usability (a bit of a loss in fact, things are
a bit slow and glitchy), but it's a necessary move if we want to use upcoming
grid-enabled userspace apps, such as a visual text editor.