\ Read the next word and return the first character ( "name" -- c ) : CHAR WORD DROP C@ ; \ Some common non-word characters : HT 9 ; \ Horizontal Tab : LF 10 ; \ Line Feed (newline) : CR 13 ; \ Carriage Return : BL 32 ; \ BLank (space) \ Emit an implementation-dependent End-of-Line sequence : .EOL LF EMIT ; \ Switch from compiling to interpreting, or vice-versa : [ FALSE STATE ! ; IMMEDIATE : ] TRUE STATE ! ; 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, , ; \ 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 \ 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 \ 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] " is equivalent to "['] COMPILE,". \ Definition has been manually expanded (vs. [COMPILE] COMPILE,) to avoid recursion. : [COMPILE] POSTPONE ['] ['] COMPILE, COMPILE, ; IMMEDIATE \ Our first control-flow primitive: IF {ELSE } THEN \ IF consumes and executes if was non-zero or else \ if 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 } clause is optional. : IF [COMPILE] 0BRANCH HERE 0 , ; IMMEDIATE : THEN HERE OVER - SWAP ! ; IMMEDIATE : ELSE [COMPILE] BRANCH HERE 0 , SWAP POSTPONE THEN ; IMMEDIATE \ Unbounded loop: BEGIN AGAIN \ BEGIN places the offset of the start of on the stack. \ AGAIN creates a relative branch back to the start of . : BEGIN HERE ; IMMEDIATE : AGAIN [COMPILE] BRANCH HERE - , ; IMMEDIATE \ Define a named constant. \ Execution: ( value "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: ( "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 "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 "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