123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- \ eForth Initial Model (8086)
- \ Based on bFORTH 1990 by Bill Muench, 1990
- \ Donated to eForth Working Group, Silicon Valley FIG Chapter
- \ to serve as a model of portable Forth for experimentation.
- \ Conventions
- \
- \ <string> characters in the input stream
- \
- \ a aligned address
- \ b byte address
- \ c character
- \ ca code address
- \ cy carry
- \ d signed double integer
- \ F logical false
- \ f flag 0 or non-zero
- \ la link address
- \ n signed integer
- \ na name address
- \ T logical true
- \ t flag T or F
- \ u unsigned integer
- \ ud unsigned double integer
- \ va vocabulary address
- \ w unspecified weighted value
- \ Header: token(ptr) link(la) name(na)
- \
- \ Count-byte and Lexicon bits ioxn nnnn
- \ i - immediate
- \ o - compile-only
- \ x - tag
- \ n - string length (31 characters MAX)
- \ Compiler does not set bits in the NAME string
- \ 0 < la na < .. < la na < va < CONTEXT @
- \ 0 < FORTH < .. < vl va < vl va < CURRENT CELL+ @
- .( Equates )
- $xxxx EQU =RP \ return stack base
- $xxxx EQU =SP \ data stack base
- $xxxx EQU =UP \ user base
- $xxxx EQU =TIB \ default Terminal Input Buffer
- $0080 EQU =IMED \ lexicom immediate bit
- $0040 EQU =COMP \ lexicom compile-only bit
- $7F1F EQU =MASK \ lexicon bit mask
- $0001 EQU =BYTE \ size of a byte
- $0002 EQU =CELL \ size of a cell
- $000A EQU =BASE \ default radix
- $0008 EQU =VOCS \ vocabulary stack depth
- $E890 EQU =CALL \ 8086 CALL opcode (NOP CALL)
- \ 8086 register useage
- \
- \ AX BX CX DX DI ES free
- \ SP data stack pointer
- \ BP return stack pointer
- \ SI interpreter pointer
- \ CS=DS=SS segment pointers
- \ IP instruction pointer
- \ The Forth inner interpreter
- \
- \ On the 8086 it is more efficient to compile
- \ the inner interpreter as inline code.
- \ On other processors it may be better
- \ to jump to the routine.
- MACRO NEXT ( -- )
- LODS WORD \ 1 byte
- JMP AX \ 2 bytes
- END-MACRO
- .( Special interpreters )
- CODE doLIT ( -- w ) COMPILE-ONLY
- LODS WORD \ r> dup 2+ >r @
- PUSH AX
- NEXT
- END-CODE
- CODE doLIST ( a -- ) \ call dolist list..
- XCHG BP, SP
- PUSH SI \ push on return stack
- XCHG BP, SP
- POP SI \ new list address
- NEXT
- END-CODE
- CODE COLD ( -- )
- JMP ORIG
- CODE BYE
- INT $20
- CODE EXECUTE ( a -- )
- POP BX
- JMP BX
- CODE EXIT ( -- )
- XCHG BP, SP
- POP SI \ pop from return stack
- XCHG BP, SP
- NEXT
- END-CODE
- .( Loop & Branch 16bit absolute address )
- \ : next ( -- ) \ hiLevel model 16bit absolute branch
- \ r> r> dup if 1 - >r @ >r exit then drop cell+ >r ;
- CODE next ( -- ) COMPILE-ONLY \ single index loop
- SUB 0 [BP], # 1 WORD \ decrement index
- U>= IF \ test index
- MOV SI, 0 [SI] \ continue looping, r> @ >r
- NEXT
- THEN
- INC BP INC BP \ drop index (pop return stack)
- LABEL noBRAN
- INC SI INC SI \ exit loop
- NEXT
- END-CODE
- CODE ?branch ( f -- ) COMPILE-ONLY
- POP BX
- OR BX, BX \ test flag
- JNZ noBRAN
- MOV SI, 0 [SI] \ branch, r> @ >r
- NEXT
- END-CODE
- CODE branch ( -- ) COMPILE-ONLY
- MOV SI, 0 [SI] \ r> @ >r
- NEXT
- END-CODE
- .( Memory fetch & store )
- CODE ! ( w a -- )
- POP BX
- POP 0 [BX]
- NEXT
- END-CODE
- CODE @ ( a -- w )
- POP BX
- PUSH 0 [BX]
- NEXT
- END-CODE
- CODE C! ( w b -- )
- POP BX
- POP AX
- MOV 0 [BX], AL
- NEXT
- END-CODE
- CODE C@ ( b -- c )
- POP BX
- XOR AX, AX
- MOV AL, 0 [BX]
- PUSH AX
- NEXT
- END-CODE
- .( Return Stack )
- CODE RP@ ( -- a )
- PUSH BP
- NEXT
- END-CODE
- CODE RP! ( a -- ) COMPILE-ONLY
- POP BP
- NEXT
- END-CODE
- CODE R> ( -- w ) COMPILE-ONLY
- PUSH 0 [BP]
- INC BP INC BP
- NEXT
- END-CODE
- CODE R@ ( -- w )
- PUSH 0 [BP]
- NEXT
- END-CODE
- CODE >R ( w -- ) COMPILE-ONLY
- DEC BP DEC BP
- POP 0 [BP]
- NEXT
- END-CODE
- .( Data Stack )
- CODE SP@ ( -- a )
- MOV BX, SP
- PUSH BX
- NEXT
- END-CODE
- CODE SP! ( a -- )
- POP SP
- NEXT
- END-CODE
- CODE DROP ( w -- )
- INC SP INC SP
- NEXT
- END-CODE
- CODE DUP ( w -- w w )
- MOV BX, SP
- PUSH 0 [BX]
- NEXT
- END-CODE
- CODE SWAP ( w1 w2 -- w2 w1 )
- POP BX
- POP AX
- PUSH BX
- PUSH AX
- NEXT
- END-CODE
- CODE OVER ( w1 w2 -- w1 w2 w1 )
- MOV BX, SP
- PUSH 2 [BX]
- NEXT
- END-CODE
- : ?DUP ( w -- w w, 0 ) DUP IF DUP THEN ;
- : NIP ( w w -- w ) SWAP DROP ;
- : ROT ( w1 w2 w3 -- w2 w3 w1 ) >R SWAP R> SWAP ;
- : 2DROP ( w w -- ) DROP DROP ;
- : 2DUP ( w1 w2 -- w1 w2 w1 w2 ) OVER OVER ;
- .( Logic )
- CODE 0< ( n -- t )
- POP AX
- CWD
- PUSH DX
- NEXT
- END-CODE
- CODE AND ( w w -- w )
- POP BX
- POP AX
- AND BX, AX
- PUSH BX
- NEXT
- END-CODE
- CODE OR ( w w -- w )
- POP BX
- POP AX
- OR BX, AX
- PUSH BX
- NEXT
- END-CODE
- CODE XOR ( w w -- w )
- POP BX
- POP AX
- XOR BX, AX
- PUSH BX
- NEXT
- END-CODE
- : INVERT ( w -- w ) -1 XOR ;
- .( Arithmetic )
- CODE UM+ ( u u -- u cy ) \ or ( u u -- ud )
- XOR CX, CX
- POP BX
- POP AX
- ADD AX, BX
- RCL CX, # 1 \ pick up carry
- PUSH AX
- PUSH CX
- NEXT
- END-CODE
- : + ( u u -- u ) UM+ DROP ;
- : NEGATE ( n -- -n ) INVERT 1 + ;
- : DNEGATE ( d -- -d ) INVERT >R INVERT 1 UM+ R> + ;
- : - ( w w -- w ) NEGATE + ;
- : ABS ( n -- +n ) DUP 0< IF NEGATE THEN ;
- .( User variables )
- : doUSER ( -- a ) R> @ UP @ + ; COMPILE-ONLY
- : doVAR ( -- a ) R> ; COMPILE-ONLY
- 8 \ start offset
- DUP USER SP0 1 CELL+ \ initial data stack pointer
- DUP USER RP0 1 CELL+ \ initial return stack pointer
- DUP USER '?KEY 1 CELL+ \ character input ready vector
- DUP USER 'EMIT 1 CELL+ \ character output vector
- DUP USER 'EXPECT 1 CELL+ \ line input vector
- DUP USER 'TAP 1 CELL+ \ input case vector
- DUP USER 'ECHO 1 CELL+ \ input echo vector
- DUP USER 'PROMPT 1 CELL+ \ operator prompt vector
- DUP USER BASE 1 CELL+ \ number base
- DUP USER temp 1 CELL+ \ scratch
- DUP USER SPAN 1 CELL+ \ #chars input by EXPECT
- DUP USER >IN 1 CELL+ \ input buffer offset
- DUP USER #TIB 1 CELL+ \ #chars in the input buffer
- 1 CELLS ALLOT \ address of input buffer
- DUP USER UP 1 CELL+ \ user base pointer
- DUP USER CSP 1 CELL+ \ save stack pointers
- DUP USER 'EVAL 1 CELL+ \ interpret/compile vector
- DUP USER 'NUMBER 1 CELL+ \ numeric input vector
- DUP USER HLD 1 CELL+ \ formated numeric string
- DUP USER HANDLER 1 CELL+ \ error frame pointer
- DUP USER CONTEXT 1 CELL+ \ first search vocabulary
- =VOCS CELL+ \ vocabulary stack
- DUP USER CURRENT 1 CELL+ \ definitions vocabulary
- 1 CELL+ \ newest vocabulary
- DUP USER CP 1 CELL+ \ dictionary code pointer
- 1 CELL+ \ dictionary name pointer
- 1 CELL+ \ last name compiled
- ?USER
- .( Comparison )
- : 0= ( w -- t ) IF 0 EXIT THEN -1 ;
- : = ( w w -- t ) XOR 0= ;
- : U< ( u u -- t ) 2DUP XOR 0< IF NIP 0< EXIT THEN - 0< ;
- : < ( n n -- t ) 2DUP XOR 0< IF DROP 0< EXIT THEN - 0< ;
- : MAX ( n n -- n ) 2DUP < IF SWAP THEN DROP ;
- : MIN ( n n -- n ) 2DUP SWAP < IF SWAP THEN DROP ;
- : WITHIN ( u ul uh -- t ) OVER - >R - R> U< ;
- .( Divide )
- : UM/MOD ( udl udh un -- ur uq )
- 2DUP U<
- IF NEGATE 15
- FOR >R DUP UM+ >R >R DUP UM+ R> + DUP
- R> R@ SWAP >R UM+ R> OR
- IF >R DROP 1 + R> ELSE DROP THEN R>
- NEXT DROP SWAP EXIT
- THEN DROP 2DROP -1 DUP ;
- : M/MOD ( d n -- r q ) \ floored
- DUP 0< DUP >R
- IF NEGATE >R DNEGATE R>
- THEN >R DUP 0< IF R@ + THEN R> UM/MOD R>
- IF SWAP NEGATE SWAP THEN ;
- : /MOD ( n n -- r q ) OVER 0< SWAP M/MOD ;
- : MOD ( n n -- r ) /MOD DROP ;
- : / ( n n -- q ) /MOD NIP ;
- .( Multiply )
- : UM* ( u1 u2 -- ud )
- 0 SWAP ( u1 0 u2 ) 15
- FOR DUP UM+ >R >R DUP UM+ R> + R>
- IF >R OVER UM+ R> + THEN
- NEXT ROT DROP ;
- : * ( n n -- n ) UM* DROP ;
- : M* ( n n -- d )
- 2DUP XOR 0< >R ABS SWAP ABS UM* R> IF DNEGATE THEN ;
- : */MOD ( n n n -- r q ) >R M* R> M/MOD ;
- : */ ( n n n -- q ) */MOD NIP ;
- .( Bits & Bytes )
- : BYTE+ ( b -- b ) [ =BYTE ] LITERAL + ;
- : CELL+ ( a -- a ) [ =CELL ] LITERAL + ;
- : CELLS ( n -- n ) [ =CELL ] LITERAL * ;
- : BL ( -- 32 ) 32 ;
- : >CHAR ( c -- c )
- 127 AND DUP 127 BL WITHIN IF [ CHAR _ ] LITERAL NIP THEN ;
- : DEPTH ( -- n ) SP@ SP0 @ SWAP - 2 / ;
- : PICK ( +n -- w ) 1 + CELLS SP@ + @ ;
- : ALIGNED ( b -- a ) ; IMMEDIATE
- .( Memory access )
- : +! ( n a -- ) SWAP OVER @ + SWAP ! ;
- : 2! ( d a -- ) SWAP OVER ! CELL+ ! ;
- : 2@ ( a -- d ) DUP CELL+ @ SWAP @ ;
- : COUNT ( b -- b +n ) DUP 1 + SWAP C@ ;
- : HERE ( -- a ) CP @ ;
- : PAD ( -- a ) HERE 80 + ;
- : TIB ( -- a ) #TIB CELL+ @ ;
- : NP ( -- a ) CP CELL+ ;
- : LAST ( -- a ) NP CELL+ ;
- : @EXECUTE ( a -- ) @ ?DUP IF EXECUTE THEN ;
- : CMOVE ( b b u -- )
- FOR AFT >R COUNT R@ C! R> 1 + THEN NEXT 2DROP ;
- : -TRAILING ( b u -- b u )
- FOR AFT DUP R@ + C@ BL XOR
- IF R> 1 + EXIT THEN THEN
- NEXT 0 ;
- : FILL ( b u c -- )
- SWAP FOR SWAP AFT 2DUP C! 1 + THEN NEXT 2DROP ;
- : ERASE ( b u -- ) 0 FILL ;
- : PACK$ ( b u a -- a ) \ null terminated
- DUP >R 2DUP C! 1 + 2DUP + 0 SWAP ! SWAP CMOVE R> ;
- .( Numeric Output ) \ single precision
- : DIGIT ( u -- c ) 9 OVER < 7 AND + [ CHAR 0 ] LITERAL + ;
- : EXTRACT ( n base -- n c ) 0 SWAP UM/MOD SWAP DIGIT ;
- : <# ( -- ) PAD HLD ! ;
- : HOLD ( c -- ) HLD @ 1 - DUP HLD ! C! ;
- : # ( u -- u ) BASE @ EXTRACT HOLD ;
- : #S ( u -- 0 ) BEGIN # DUP WHILE REPEAT ;
- : SIGN ( n -- ) 0< IF [ CHAR - ] LITERAL HOLD THEN ;
- : #> ( w -- b u ) DROP HLD @ PAD OVER - ;
- : str ( w -- b u ) DUP >R ABS <# #S R> SIGN #> ;
- : HEX ( -- ) 16 BASE ! ;
- : DECIMAL ( -- ) 10 BASE ! ;
- .( Numeric Input ) \ single precision
- : DIGIT? ( c base -- u t )
- >R [ CHAR 0 ] LITERAL - 9 OVER <
- IF 7 - DUP 10 < OR THEN DUP R> U< ;
- : NUMBER? ( a -- n T, a F )
- BASE @ >R 0 OVER COUNT ( a 0 b n)
- OVER C@ [ CHAR $ ] LITERAL =
- IF HEX SWAP BYTE+ SWAP 1 - THEN ( a 0 b' n')
- OVER C@ [ CHAR - ] LITERAL = >R ( a 0 b n)
- SWAP R@ - SWAP R@ + ( a 0 b" n") ?DUP
- IF 1 - ( a 0 b n)
- FOR DUP >R C@ BASE @ DIGIT?
- WHILE SWAP BASE @ * + R> BYTE+
- NEXT R@ ( ?sign) NIP ( b) IF NEGATE THEN SWAP
- ELSE R> R> ( b index) 2DROP ( digit number) 2DROP 0
- THEN DUP
- THEN R> ( n ?sign) 2DROP R> BASE ! ;
- .( Basic I/O )
- : KEY? ( -- f ) '?KEY @EXECUTE ;
- : KEY ( -- c ) BEGIN '?KEY UNTIL ;
- : EMIT ( c -- ) 'EMIT @EXECUTE ;
- : NUF? ( -- f ) KEY? DUP IF KEY 2DROP KEY 13 = THEN ;
- : PACE ( -- ) 11 EMIT ;
- : SPACE ( -- ) BL EMIT ;
- : CHARS ( +n c -- ) SWAP 0 MAX FOR AFT DUP EMIT THEN NEXT DROP ;
- : SPACES ( +n -- ) BL CHARS ;
- : do$ ( -- a )
- R> R@ R> COUNT + ALIGNED >R SWAP >R ; COMPILE-ONLY
- : $"| ( -- a ) do$ ; COMPILE-ONLY
- : TYPE ( b u -- ) FOR AFT COUNT EMIT THEN NEXT DROP ;
- : .$ ( a -- ) COUNT TYPE ;
- : ."| ( -- ) do$ .$ ; COMPILE-ONLY
- : CR ( -- ) 13 EMIT 10 EMIT ;
- : .R ( n +n -- ) >R str R> OVER - SPACES TYPE ;
- : U.R ( u +n -- ) >R <# #S #> R> OVER - SPACES TYPE ;
- : U. ( u -- ) <# #S #> SPACE TYPE ;
- : . ( w -- ) BASE @ 10 XOR IF U. EXIT THEN str SPACE TYPE ;
- : ? ( a -- ) @ . ;
- .( Parsing )
- : parse ( b u c -- b u delta \ <string> )
- temp ! OVER >R DUP \ b u u
- IF 1 - temp @ BL =
- IF \ b u' \ 'skip'
- FOR COUNT temp @ SWAP - 0< INVERT WHILE
- NEXT ( b) R> DROP 0 DUP EXIT \ all delim
- THEN 1 - R>
- THEN OVER SWAP \ b' b' u' \ 'scan'
- FOR COUNT temp @ SWAP - temp @ BL =
- IF 0< THEN WHILE
- NEXT DUP >R ELSE R> DROP DUP >R 1 -
- THEN OVER - R> R> - EXIT
- THEN ( b u) OVER R> - ;
- : PARSE ( c -- b u \ <string> )
- >R TIB >IN @ + #TIB @ >IN @ - R> parse >IN +! ;
- : .( ( -- ) [ CHAR ) ] LITERAL PARSE TYPE ; IMMEDIATE
- : ( ( -- ) [ CHAR ) ] LITERAL PARSE 2DROP ; IMMEDIATE
- : \ ( -- ) #TIB @ >IN ! ; IMMEDIATE
- : CHAR ( -- c ) BL PARSE DROP C@ ;
- : CTRL ( -- c ) CHAR $001F AND ;
- : TOKEN ( -- a \ <string> )
- BL PARSE 31 MIN NP @ OVER - 2 - PACK$ ;
- : WORD ( c -- a \ <string> ) PARSE HERE PACK$ ;
- .( Dictionary Search )
- : NAME> ( na -- ca ) 2 CELLS - @ ;
- : SAME? ( a a u -- a a f \ -0+ )
- FOR AFT OVER R@ CELLS + @
- OVER R@ CELLS + @ - ?DUP
- IF R> DROP EXIT THEN THEN
- NEXT 0 ;
- : find ( a va -- ca na, a F )
- SWAP \ va a
- DUP C@ 2 / temp ! \ va a \ get cell count
- DUP @ >R \ va a \ count byte & 1st char
- CELL+ SWAP \ a' va
- BEGIN @ DUP \ a' na na
- IF DUP @ [ =MASK ] LITERAL AND R@ XOR \ ignore lexicon bits
- IF CELL+ -1 ELSE CELL+ temp @ SAME? THEN
- ELSE R> DROP EXIT
- THEN
- WHILE 2 CELLS - \ a' la
- REPEAT R> DROP NIP 1 CELLS - DUP NAME> SWAP ;
- : NAME? ( a -- ca na, a F )
- CONTEXT DUP 2@ XOR IF 1 CELLS - THEN >R \ context<>also
- BEGIN R> CELL+ DUP >R @ ?DUP
- WHILE find ?DUP
- UNTIL R> DROP EXIT THEN R> DROP 0 ;
- .( Terminal )
- : ^H ( b b b -- b b b ) \ backspace
- >R OVER R@ < DUP
- IF [ CTRL H ] LITERAL 'ECHO @EXECUTE THEN R> + ;
- : TAP ( bot eot cur key -- bot eot cur )
- DUP 'ECHO @EXECUTE OVER C! 1 + ;
- : kTAP ( bot eot cur key -- bot eot cur )
- DUP 13 XOR
- IF [ CTRL H ] LITERAL XOR IF BL TAP ELSE ^H THEN EXIT
- THEN DROP NIP DUP ;
- : accept ( b u -- b u )
- OVER + OVER
- BEGIN 2DUP XOR
- WHILE KEY DUP BL - 95 U<
- IF TAP ELSE 'TAP @EXECUTE THEN
- REPEAT DROP OVER - ;
- : EXPECT ( b u -- ) 'EXPECT @EXECUTE SPAN ! DROP ;
- : QUERY ( -- )
- TIB 80 'EXPECT @EXECUTE #TIB ! 0 NIP >IN ! ;
- .( Error handling )
- : CATCH ( ca -- err#/0 )
- SP@ >R HANDLER @ >R RP@ HANDLER !
- EXECUTE
- R> HANDLER ! R> DROP 0 ;
- : THROW ( err# -- err# )
- HANDLER @ RP! R> HANDLER ! R> SWAP >R SP! DROP R> ;
- CREATE NULL$ 0 ,
- : ABORT ( -- ) NULL$ THROW ;
- : abort" ( f -- ) IF do$ THROW THEN do$ DROP ; COMPILE-ONLY
- .( Interpret )
- : $INTERPRET ( a -- )
- NAME? ?DUP
- IF @ [ =COMP ] LITERAL AND
- ABORT" compile ONLY" EXECUTE EXIT
- THEN
- 'NUMBER @EXECUTE
- IF EXIT THEN THROW ;
- : [ ( -- ) [ ' $INTERPRET ] LITERAL 'EVAL ! ; IMMEDIATE
- : .OK ( -- ) [ ' $INTERPRET ] LITERAL 'EVAL @ = IF ." ok" THEN CR ;
- : ?STACK ( -- ) DEPTH 0< IF $" underflow" THROW THEN ;
- : EVAL ( -- )
- BEGIN TOKEN DUP C@
- WHILE 'EVAL @EXECUTE ?STACK
- REPEAT DROP 'PROMPT @EXECUTE ;
- .( Device I/O )
- CODE IO? ( -- f ) \ FFFF is an impossible character
- XOR BX, BX
- MOV DL, # $0FF \ input
- MOV AH, # 6 \ MS-DOS Direct Console I/O
- INT $021
- 0<> IF \ ?key ready
- OR AL, AL
- 0= IF \ ?extended ascii code
- INT $021
- MOV BH, AL \ extended code in msb
- ELSE MOV BL, AL
- THEN
- PUSH BX
- MOVE BX, # -1
- THEN
- PUSH BX
- NEXT
- END-CODE
- CODE TX! ( c -- )
- POP DX
- CMP DL, # $0FF
- 0= IF \ do NOT allow input
- MOV DL, # 32 \ change to blank
- THEN
- MOV AH, # 6 \ MS-DOS Direct Console I/O
- INT $021
- NEXT
- END-CODE
- : !IO ( -- ) ; IMMEDIATE \ initialize I/O device
- .( Shell )
- : PRESET ( -- ) SP0 @ SP! [ =TIB ] LITERAL #TIB CELL+ ! ;
- : XIO ( a a a -- ) \ reset 'EXPECT 'TAP 'ECHO 'PROMPT
- [ ' accept ] LITERAL 'EXPECT !
- 'TAP ! 'ECHO ! 'PROMPT ! ;
- : FILE ( -- )
- [ ' PACE ] LITERAL [ ' DROP ] LITERAL [ ' kTAP ] LITERAL XIO ;
- : HAND ( -- )
- [ ' .OK ] LITERAL 'EMIT @ [ ' kTAP ] LITERAL XIO ;
- CREATE I/O ' RX? , ' TX! , \ defaults
- : CONSOLE ( -- ) I/O 2@ 'KEY? 2! HAND ;
- : que ( -- ) QUERY EVAL ;
- : QUIT ( -- ) \ clear return stack ONLY
- RP0 @ RP!
- BEGIN [COMPILE] [
- BEGIN [ ' que ] LITERAL CATCH ?DUP
- UNTIL ( a)
- CONSOLE NULL$ OVER XOR
- IF CR TIB #TIB @ TYPE
- CR >IN @ [ CHAR ^ ] LITERAL CHARS
- CR .$ ." ? "
- THEN PRESET
- AGAIN ;
- .( Compiler Primitives )
- : ' ( -- ca ) TOKEN NAME? IF EXIT THEN THROW ;
- : ALLOT ( n -- ) CP +! ;
- : , ( w -- ) HERE ALIGNED DUP CELL+ CP ! ! ;
- : [COMPILE] ( -- \ <string> ) ' , ; IMMEDIATE
- : COMPILE ( -- ) R> DUP @ , CELL+ >R ; COMPILE-ONLY
- : LITERAL ( w -- ) COMPILE doLIT , ; IMMEDIATE
- : $," ( -- ) [ CHAR " ] LITERAL PARSE HERE PACK$ C@ 1 + ALLOT ;
- : RECURSE ( -- ) LAST @ CURRENT @ ! ; IMMEDIATE
- .( Structures )
- : FOR ( -- a ) COMPILE >R HERE ; IMMEDIATE
- : BEGIN ( -- a ) HERE ; IMMEDIATE
- : NEXT ( a -- ) COMPILE next , ; IMMEDIATE
- : UNTIL ( a -- ) COMPILE ?branch , ; IMMEDIATE
- : AGAIN ( a -- ) COMPILE branch , ; IMMEDIATE
- : IF ( -- A ) COMPILE ?branch HERE 0 , ; IMMEDIATE
- : AHEAD ( -- A ) COMPILE branch HERE 0 , ; IMMEDIATE
- : REPEAT ( A a -- ) [COMPILE] AGAIN HERE SWAP ! ; IMMEDIATE
- : THEN ( A -- ) HERE SWAP ! ; IMMEDIATE
- : AFT ( a -- a A ) DROP [COMPILE] AHEAD [COMPILE] BEGIN SWAP ; IMMEDIATE
- : ELSE ( A -- A ) [COMPILE] AHEAD SWAP [COMPILE] THEN ; IMMEDIATE
- : WHILE ( a -- A a ) [COMPILE] IF SWAP ; IMMEDIATE
- : ABORT" ( -- \ <string> ) COMPILE abort" $," ; IMMEDIATE
- : $" ( -- \ <string> ) COMPILE $"| $," ; IMMEDIATE
- : ." ( -- \ <string> ) COMPILE ."| $," ; IMMEDIATE
- .( Name Compiler )
- : ?UNIQUE ( a -- a )
- DUP NAME? IF ." reDef " OVER .$ THEN DROP ;
- : $,n ( na -- )
- DUP C@
- IF ?UNIQUE
- ( na) DUP LAST ! \ for OVERT
- ( na) HERE ALIGNED SWAP
- ( cp na) 1 CELLS -
- ( cp la) CURRENT @ @
- ( cp la na') OVER !
- ( cp la) 1 CELLS - DUP NP ! ( ptr) ! EXIT
- THEN $" name" THROW ;
- .( FORTH Compiler )
- : $COMPILE ( a -- )
- NAME? ?DUP
- IF C@ [ =IMED ] LITERAL AND
- IF EXECUTE ELSE , THEN EXIT
- THEN
- 'NUMBER @EXECUTE
- IF [COMPILE] LITERAL EXIT
- THEN THROW ;
- : OVERT ( -- ) LAST @ CURRENT @ ! ;
- : ; ( -- )
- COMPILE EXIT [COMPILE] [ OVERT ; COMPILE-ONLY IMMEDIATE
- : ] ( -- ) [ ' $COMPILE ] LITERAL 'EVAL ! ;
- : CALL, ( ca -- ) \ DTC 8086 relative call
- [ =CALL ] LITERAL , HERE CELL+ - , ;
- : : ( -- \ <string> ) TOKEN $,n [ ' doLIST ] LITERAL CALL, ] ;
- : IMMEDIATE ( -- ) [ =IMED ] LITERAL LAST @ C@ OR LAST @ C! ;
- .( Defining Words )
- : USER ( u -- \ <string> ) TOKEN $,n OVERT COMPILE doUSER , ;
- : CREATE ( -- \ <string> ) TOKEN $,n OVERT COMPILE doVAR ;
- : VARIABLE ( -- \ <string> ) CREATE 0 , ;
- .( Tools )
- : _TYPE ( b u -- ) FOR AFT COUNT >CHAR EMIT THEN NEXT DROP ;
- : dm+ ( b u -- b )
- OVER 4 U.R SPACE FOR AFT COUNT 3 U.R THEN NEXT ;
- : DUMP ( b u -- )
- BASE @ >R HEX 16 /
- FOR CR 16 2DUP dm+ -ROT 2 SPACES _TYPE NUF? 0= WHILE
- NEXT ELSE R> DROP THEN DROP R> BASE ! ;
- : .S ( -- ) CR DEPTH FOR AFT R@ PICK . THEN NEXT ." <tos" ;
- : !CSP ( -- ) SP@ CSP ! ;
- : ?CSP ( -- ) SP@ CSP @ XOR ABORT" stack depth" ;
- : >NAME ( ca -- na, F )
- CURRENT
- BEGIN CELL+ @ ?DUP WHILE 2DUP
- BEGIN @ DUP WHILE 2DUP NAME> XOR
- WHILE 1 CELLS -
- REPEAT THEN NIP ?DUP
- UNTIL NIP NIP EXIT THEN 0 NIP ;
- : .ID ( na -- )
- ?DUP IF COUNT $001F AND TYPE EXIT THEN ." {noName}" ;
- : WORDS ( -- )
- CR CONTEXT @
- BEGIN @ ?DUP
- WHILE DUP SPACE .ID 1 CELLS - NUF?
- UNTIL DROP THEN ;
- .( Hardware reset )
- \ version
- $100 CONSTANT VER ( -- u )
- \ hi byte = major revision in decimal
- \ lo byte = minor revision in decimal
- : hi ( -- )
- !IO \ initialize IO device & sign on
- CR ." eForth v1.0"
- ; COMPILE-ONLY
- CREATE 'BOOT ' hi , \ application vector
- : COLD ( -- )
- \ init CPU
- \ init stacks
- \ init user area
- \ init IP
- PRESET 'BOOT @EXECUTE
- QUIT ;
|