revise startup code with comments and new definitions
This commit is contained in:
parent
09afabc21c
commit
2d8f282611
89
startup.4th
89
startup.4th
|
|
@ -1,30 +1,93 @@
|
||||||
|
\ Read the next word and return the first character
|
||||||
|
( "<spaces>name" -- c )
|
||||||
: CHAR WORD DROP C@ ;
|
: CHAR WORD DROP C@ ;
|
||||||
|
|
||||||
: TAB 9 EMIT ;
|
\ Some common non-word characters
|
||||||
: LF 10 EMIT ;
|
: HT 9 ; \ Horizontal Tab
|
||||||
: SPACE 32 EMIT ;
|
: LF 10 ; \ Line Feed (newline)
|
||||||
|
: CR 13 ; \ Carriage Return
|
||||||
|
: BL 32 ; \ BLank (space)
|
||||||
|
|
||||||
: BANNER "JumpForth version " .S VERSION . ", by Jesse McDonald" .S LF ;
|
\ Emit an implementation-dependent End-of-Line sequence
|
||||||
|
: .EOL LF EMIT ;
|
||||||
|
|
||||||
|
\ Switch from compiling to interpreting, or vice-versa
|
||||||
: [ FALSE STATE ! ; IMMEDIATE
|
: [ FALSE STATE ! ; IMMEDIATE
|
||||||
: ] TRUE STATE ! ; IMMEDIATE
|
: ] TRUE STATE ! ; IMMEDIATE
|
||||||
|
|
||||||
: POSTPONE WORD FINDERR , ; IMMEDIATE
|
\ COMPILE, appends the effect of the execution token on the top of the stack
|
||||||
|
\ to the current definition. In this implementation it's equivalent to , since
|
||||||
|
\ definitions are just arrays of execution tokens.
|
||||||
: COMPILE, , ;
|
: COMPILE, , ;
|
||||||
|
|
||||||
: ['] [ ' LIT , ' LIT , ] , ' , ; IMMEDIATE
|
\ Read a word and append it to the current definition, ignoring the IMMED flag.
|
||||||
|
\ This is used to "call" an immediate word as a normal function.
|
||||||
|
\ POSTPONE has no effect (as a modifier) if the IMMED flag is not set.
|
||||||
|
: POSTPONE WORD FINDERR COMPILE, ; IMMEDIATE
|
||||||
|
|
||||||
: LITERAL ['] LIT , , ; IMMEDIATE
|
\ Append the LIT xt and the topmost word on the stack to the current definition.
|
||||||
|
\ If [COMPILE] were already defined then this could simply be written as:
|
||||||
|
\
|
||||||
|
\ : LITERAL [COMPILE] LIT , ; IMMEDIATE
|
||||||
|
\
|
||||||
|
\ ... but since it isn't we must manually insert the LIT sequence to obtain the
|
||||||
|
\ address of LIT as a literal to be compiled into the current definition.
|
||||||
|
: LITERAL [ ' LIT COMPILE, ' LIT , ] COMPILE, , ; IMMEDIATE
|
||||||
|
|
||||||
: IF ['] 0BRANCH , HERE 0 , ; IMMEDIATE
|
\ Like CHAR, but generates a literal at compile-time.
|
||||||
|
: [CHAR] CHAR POSTPONE LITERAL ; IMMEDIATE
|
||||||
|
|
||||||
|
\ Like ', but generates a literal at compile-time.
|
||||||
|
: ['] ' POSTPONE LITERAL ; IMMEDIATE
|
||||||
|
|
||||||
|
\ "[COMPILE] <word>" is equivalent to "['] <word> COMPILE,".
|
||||||
|
\ Definition has been manually expanded (vs. [COMPILE] COMPILE,) to avoid recursion.
|
||||||
|
: [COMPILE] POSTPONE ['] ['] COMPILE, COMPILE, ; IMMEDIATE
|
||||||
|
|
||||||
|
\ Our first control-flow primitive: <cond> IF <true> {ELSE <false>} THEN
|
||||||
|
\ IF consumes <cond> and executes <true> if <cond> was non-zero or else
|
||||||
|
\ <false> if <cond> was zero. In either case execution continues after THEN.
|
||||||
|
\ IF and ELSE leave the address of the latest branch "hole" on the data stack.
|
||||||
|
\ ELSE and THEN fill in the previous "hole" with the relative branch offset.
|
||||||
|
\ The {ELSE <false>} clause is optional.
|
||||||
|
: IF [COMPILE] 0BRANCH HERE 0 , ; IMMEDIATE
|
||||||
: THEN HERE OVER - SWAP ! ; IMMEDIATE
|
: THEN HERE OVER - SWAP ! ; IMMEDIATE
|
||||||
: ELSE POSTPONE THEN ['] BRANCH , HERE 0 , ; IMMEDIATE
|
: ELSE [COMPILE] BRANCH HERE 0 , SWAP POSTPONE THEN ; IMMEDIATE
|
||||||
|
|
||||||
|
\ Unbounded loop: BEGIN <code> AGAIN
|
||||||
|
\ BEGIN places the offset of the start of <code> on the stack.
|
||||||
|
\ AGAIN creates a relative branch back to the start of <code>.
|
||||||
: BEGIN HERE ; IMMEDIATE
|
: BEGIN HERE ; IMMEDIATE
|
||||||
: AGAIN ['] BRANCH , HERE - , ; IMMEDIATE
|
: AGAIN [COMPILE] BRANCH HERE - , ; IMMEDIATE
|
||||||
|
|
||||||
CREATE VAR 123 , DOES> @ ;
|
\ Define a named constant.
|
||||||
: VAR! [ ' VAR >BODY ] LITERAL ! ;
|
\ Execution: ( value "<spaces>name" -- )
|
||||||
|
\ name Execution: ( -- value )
|
||||||
|
: CONSTANT : POSTPONE LITERAL POSTPONE ; ;
|
||||||
|
|
||||||
|
\ Define a single-cell named variable which returns its data address when executed.
|
||||||
|
\ The initial value is formally undefined. This implementation sets it to zero.
|
||||||
|
\ Execution: ( "<spaces>name" -- )
|
||||||
|
\ name Execution: ( -- a-addr )
|
||||||
|
: VARIABLE CREATE 0 , ;
|
||||||
|
|
||||||
|
\ Define a single-cell named value which returns its data (not address) when executed.
|
||||||
|
\ Named values defined with VALUE can be modified with TO.
|
||||||
|
\ Execution: ( x "<spaces>name" -- )
|
||||||
|
\ name execution: ( -- value )
|
||||||
|
: VALUE CREATE , POSTPONE DOES> [COMPILE] @ POSTPONE ; ;
|
||||||
|
|
||||||
|
\ When compiling, append code to store to the data field area of the named value.
|
||||||
|
\ When interpreting, store to the data field directly.
|
||||||
|
\ An ambiguous condition exists if the name was not created with VALUE.
|
||||||
|
( x "<spaces>name" -- )
|
||||||
|
: TO ' >BODY STATE @ IF POSTPONE LITERAL [COMPILE] ! ELSE ! THEN ; IMMEDIATE
|
||||||
|
|
||||||
|
: / /MOD NIP ;
|
||||||
|
: MOD /MOD DROP ;
|
||||||
|
|
||||||
|
: DEPTH SP@ S0 SWAP - CELL / ;
|
||||||
|
|
||||||
|
: BANNER "JumpForth version " .S VERSION . ", by Jesse McDonald" .S .EOL ;
|
||||||
|
|
||||||
BANNER
|
BANNER
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue