+: TO IMMEDIATE ( n -- )
+ WORD ( get the name of the value )
+ FIND ( look it up in the dictionary )
+ >DFA ( get a pointer to the first data field (the 'LIT') )
+ 4+ ( increment to point at the value )
+ STATE @ IF ( compiling? )
+ ' LIT , ( compile LIT )
+ , ( compile the address of the value )
+ ' ! , ( compile ! )
+ ELSE ( immediate mode )
+ ! ( update it straightaway )
+ THEN
+;
+
+(
+ ID. takes an address of a dictionary entry and prints the word's name.
+
+ For example: LATEST @ ID. would print the name of the last word that was defined.
+)
+: ID.
+ 4+ ( skip over the link pointer )
+ DUP @b ( get the flags/length byte )
+ F_LENMASK AND ( mask out the flags - just want the length )
+
+ BEGIN
+ DUP 0> ( length > 0? )
+ WHILE
+ SWAP 1+ ( addr len -- len addr+1 )
+ DUP @b ( len addr -- len addr char | get the next character)
+ EMIT ( len addr char -- len addr | and print it)
+ SWAP 1- ( len addr -- addr len-1 | subtract one from length )
+ REPEAT
+ DROP DROP ( len addr -- )
+;
+
+(
+ WORDS prints all the words defined in the dictionary, starting with the word defined most recently.
+
+ The implementation simply iterates backwards from LATEST using the link pointers.
+)
+: WORDS
+ LATEST @ ( start at LATEST dictionary entry )
+ BEGIN
+ DUP 0<> ( while link pointer is not null )
+ WHILE
+ DUP ID. ( print the word )
+ SPACE
+ @ ( dereference the link pointer - go to previous word )
+ REPEAT
+ DROP
+ CR
+;
+
+(
+ So far we have only allocated words and memory. FORTH provides a rather primitive method
+ to deallocate.
+
+ 'FORGET word' deletes the definition of 'word' from the dictionary and everything defined
+ after it, including any variables and other memory allocated after.
+
+ The implementation is very simple - we look up the word (which returns the dictionary entry
+ address). Then we set HERE to point to that address, so in effect all future allocations
+ and definitions will overwrite memory starting at the word. We also need to set LATEST to
+ point to the previous word.
+
+ Note that you cannot FORGET built-in words (well, you can try but it will probably cause
+ a segfault).
+
+ XXX: Because we wrote VARIABLE to store the variable in memory allocated before the word,
+ in the current implementation VARIABLE FOO FORGET FOO will leak 1 cell of memory.
+)
+\\: FORGET
+
+
+
+( While compiling, [COMPILE] WORD compiles WORD if it would otherwise be IMMEDIATE. )
+: [COMPILE] IMMEDIATE
+ WORD ( get the next word )
+ FIND ( find it in the dictionary )
+ >CFA ( get its codeword )
+ , ( and compile that )
+;
+
+(
+ RECURSE makes a recursive call to the current word that is being compiled.
+
+ Normally while a word is being compiled, it is marked HIDDEN so that references to the
+ same word within are calls to the previous definition of the word. However we still have
+ access to the word which we are currently compiling through the LATEST pointer so we
+ can use that to compile a recursive call.
+)
+: RECURSE IMMEDIATE
+ LATEST @ >CFA ( LATEST points to the word being compiled at the moment )
+ , ( compile it )
+;
+
+( Finally print the welcome prompt. )
+.\" JONESFORTH VERSION \" VERSION . CR