home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / forth / compiler / eforth / eforth.old < prev    next >
Text File  |  1990-07-26  |  47KB  |  2,100 lines

  1. TITLE 8086 eForth
  2. NAME eForth
  3. PAGE 62,132    ;62 lines per page, 132 characters per line
  4. .SALL        ;Suppress listing of macro expressions
  5. .XCREF        ;Suppress generating cross-references
  6.  
  7. ;====================================================================
  8. ;
  9. ;    eForth 1.0 by Bill Muench and C. H. Ting, 1990
  10. ;    Much of the code is derived from the following two sources:
  11. ;        8086 figForth by Thomas Newman, 1981 and Joe smith, 1983
  12. ;        bFORTH by Bill Muench, 1990
  13. ;
  14. ;    The goal of this implementation is to provide a simple eForth Model
  15. ;    which can be ported easily to many 8, 16, 24 and 32 bit CPU's.
  16. ;    The following attributes make it suitable for CPU's of the '90:
  17. ;
  18. ;        small machine dependent kernel and portable high level code
  19. ;        source code in the MASM format
  20. ;        direct threaded code
  21. ;        separated code and name dictionaries
  22. ;        simple vectored terminal and file interface to host computer
  23. ;        aligned with the proposed ANS Forth Standard
  24. ;        easy upgrade path to optimize for specific CPU
  25. ;
  26. ;    You are invited to implement this Model on your favorite CPU and
  27. ;    contribute it to the eForth Library for public use. You may use
  28. ;    a portable implementation to advertise more sophisticated and
  29. ;    optimized version for commercial purposes. However, you are
  30. ;    expected to implement the Model faithfully. The eForth Working
  31. ;    Group reserves the right to reject implementation which deviates
  32. ;    significantly from this Model.
  33. ;
  34. ;    As the ANS Forth Standard is still evolving, this Model will
  35. ;    change accordingly. Implementations must state clearly the
  36. ;    version number of the Model being tracked.
  37. ;
  38. ;    Representing the eForth Working Group in the Silicon Valley FIG Chapter.
  39. ;    Contributions must be sent to:
  40. ;
  41. ;        Dr. C. H. Ting
  42. ;        156 14th Avenue
  43. ;        San Mateo, CA  94402
  44. ;        (415) 571-7639
  45. ;
  46. ;===================================================================
  47.  
  48. ;; Version control
  49.  
  50. VER        EQU    1            ;major release version
  51. EXT        EQU    0            ;minor extension
  52.  
  53. ;; Memory allocation
  54.  
  55. EM        EQU    4000H            ;top of memory
  56. US        EQU    128            ;user area size in bytes
  57. RTS        EQU    256            ;return stack/TIB size
  58.  
  59. UPP        EQU    EM-US            ;start of user area (UP0)
  60. RPP        EQU    UPP-2            ;start of return stack (RP0)
  61. TIBB        EQU    UPP-RTS            ;terminal input buffer (TIB)
  62. SPP        EQU    RPP-RTS            ;start of data stack (SP0)
  63.  
  64. NAMEE        EQU    3C00H            ;name dictionary
  65. COLDD        EQU    0100H            ;cold start vector
  66. CODEE        EQU    COLDD+US        ;code dictionary
  67.  
  68. ;; Constants and equates
  69.  
  70. FALSS        EQU    0            ;false flag
  71. TRUEE        EQU    -1            ;true flag
  72.  
  73. IMEDD        EQU    80H            ;lexicon immediate bit
  74. COMPO        EQU    40H            ;lexicon compile only bit
  75. MASKK        EQU    7F1FH            ;lexicon bit mask
  76.  
  77. CELLL        EQU    2            ;size of a cell
  78. BASEE        EQU    10            ;default radix
  79. VOCSS        EQU    8            ;depth of vocabulary stack
  80.  
  81. BKSPP        EQU    8            ;back space
  82. LF        EQU    10            ;line feed
  83. CRR        EQU    13            ;carriage return
  84. ERR        EQU    27            ;error escape
  85. TIC        EQU    39            ;tick
  86.  
  87. CALLL        EQU    0E890H            ;NOP CALL opcodes
  88.  
  89. ;; Initialize assembly variables
  90.  
  91. _LINK    = 0                    ;force a null link
  92. _NAME    = NAMEE                    ;name space pointer
  93. _CODE    = CODEE                    ;save code space pointer
  94. _USER    = 4*CELLL                ;first user variable offset
  95.  
  96. ;; Define assembly macros
  97.  
  98. ;    Compile a eForth name field
  99. ;    Lay down the header backwards in memory
  100.  
  101. $NAME    MACRO    LBYTE,NAME,LABEL,TACKY
  102.     EVEN                    ;;fill NOP to cell boundary
  103. LABEL:                        ;;label to be used in definitions
  104.     _CODE    = $                ;;save code pointer for token
  105.     _NAME    = _NAME-(LBYTE AND 1EH)-CELLL*3    ;;new header on cell boundary.
  106. ORG     _NAME
  107.     DW     _CODE                ;;token feild
  108.     DW     _LINK                ;;link field
  109.     _LINK    = $                ;;next link points to name field
  110.     DB    LBYTE                ;;length
  111.     IFNB    <TACKY>
  112.     DB    "&NAME"                ;;name contains a '
  113.     ELSE
  114.     DB    '&NAME'                ;;name may contain a "
  115.     ENDIF
  116. ORG     _CODE                    ;;restore code pointer
  117.     ENDM
  118.  
  119. ;    Compile a code definition header.
  120.  
  121. $CODE    MACRO    ONE,TWO,THREE,FOUR
  122.     $NAME    ONE,TWO,THREE,FOUR
  123.     ENDM
  124.  
  125. ;    Compile a colon definition header.
  126.  
  127. $COLON    MACRO    ONE,TWO,THREE,FOUR
  128.     $NAME    ONE,TWO,THREE,FOUR
  129.     NOP                    ;;align to cell boundary
  130.     CALL    DOLST                ;;include CALL doLIST
  131.     ENDM
  132.  
  133. ;    Compile a user variable header.
  134.  
  135. $USER    MACRO    ONE,TWO,THREE,FOUR
  136.     $NAME    ONE,TWO,THREE,FOUR
  137.     NOP                    ;;align to cell boundary
  138.     CALL    DOLST                ;;include CALL doLIST
  139.     DW    DOUSE                ;;followed by doUSER
  140.     DW    _USER                ;;and the user area offset
  141.     _USER = _USER+CELLL            ;;update user area offset
  142.     ENDM
  143.  
  144. ;    Assemble inline direct threaded code ending.
  145.  
  146. $NEXT    MACRO
  147.     LODSW                    ;;read code address of next word into AX
  148.     JMP    AX                ;;jump directly to the code address
  149.     ENDM
  150.  
  151. ;; Main entry points and COLD start data
  152.  
  153. MAIN    SEGMENT
  154.     ASSUME    CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN
  155.  
  156. ORG    COLDD                    ;beginning of cold boot area
  157.  
  158. ORIG:        MOV    AX,CS
  159.         MOV    DS,AX            ;all in one segment
  160.         CLI                ;disable interrupt for old 808x CPU bug
  161.         MOV    SS,AX
  162.         MOV    SP,SPP            ;initialize SP
  163.         STI
  164.         MOV    BP,RPP            ;initialize RP
  165.         MOV    AL,23H            ;^C interrupt INT23
  166.         MOV    DX,OFFSET CTRLC
  167.         MOV    AH,25H            ;set ^C address
  168.         INT    21H
  169.         CLD                ;SI gets incremented
  170.         MOV    SI,OFFSET COLD1
  171.         $NEXT                ;to high level cold start
  172.  
  173. CTRLC:        IRET                ;just return from ^C interrupt INT 23H
  174.  
  175. ; COLD start moves the following to USER variables.
  176. ; MUST BE IN SAME ORDER AS USER VARIABLES
  177.  
  178. EVEN                        ;align to cell boundary
  179.  
  180. UZERO:        DW    4 DUP (0)        ;reserved space in user area
  181.         DW    SPP            ;SP0
  182.         DW    RPP            ;RP0
  183.         DW    QRX            ;'?KEY
  184.         DW    STOTX            ;'EMIT
  185.         DW    ACCEP            ;'EXPECT
  186.         DW    KTAP            ;'TAP
  187.         DW    STOTX            ;'ECHO
  188.         DW    DOTOK            ;'PROMPT
  189.         DW    BASEE            ;BASE
  190.         DW    0            ;tmp
  191.         DW    0            ;SPAN
  192.         DW    0            ;>IN
  193.         DW    0            ;#TIB
  194.         DW    TIBB            ;TIB
  195.         DW    0            ;CSP
  196.         DW    INTER            ;'EVAL
  197.         DW    NUMBQ            ;'NUMBER
  198.         DW    0            ;HLD
  199.         DW    0            ;HANDLER
  200.         DW    UPP+V4TH-UZERO        ;CONTEXT point to FORTH
  201.         DW    VOCSS DUP (0)        ;vocabulary stack
  202.         DW    UPP+V4TH-UZERO        ;CURRENT point to FORTH
  203.         DW    V4TH            ;voc-link
  204.         DW    CTOP            ;CP
  205.         DW    NTOP            ;NP
  206.         DW    LASTN            ;LAST
  207.  
  208. V4TH:        DW    LASTN,0            ;simple FORTH vocabulary
  209.         DW    6 DUP (0)        ;3 more vocabularies
  210.  
  211. ULAST:
  212.  
  213. ;; The kernel
  214.  
  215. ORG    CODEE                    ;beginning of the code dictionary
  216.  
  217. ;=C   doLIT    ( -- w )
  218. ;        Push an inline literal.
  219.  
  220.         $CODE    COMPO+5,doLIT,DOLIT
  221.         LODSW
  222.         PUSH    AX
  223.         $NEXT
  224.  
  225. ;=C   doLIST    ( a -- )
  226. ;        Process colon list.
  227.  
  228.         $CODE    COMPO+6,doLIST,DOLST
  229.         XCHG    BP,SP            ;exchange the return and data stack pointers
  230.         PUSH    SI            ;push on return stack
  231.         XCHG    BP,SP            ;restore the pointers
  232.         POP    SI            ;new list address
  233.         $NEXT
  234.  
  235. ;=C   next    ( -- )
  236. ;        Run time code for the single index loop.
  237.  
  238.         $CODE    COMPO+4,next,DONXT
  239.         SUB    WORD PTR [BP],1        ;decrement the index
  240.         JC    NEXT1            ;?decrement below 0
  241.         MOV    SI,0[SI]        ;no, branch back again
  242.         $NEXT
  243. NEXT1:        INC    BP            ;yes, pop the index
  244.         INC    BP
  245.         INC    SI            ;continue past the branch offset
  246.         INC    SI
  247.         $NEXT
  248.  
  249. ;=C   ?branch    ( f -- )
  250. ;        Branch if flag is zero.
  251.  
  252.         $CODE    COMPO+7,?branch,QBRAN
  253.         POP    BX            ;pop flag
  254.         OR    BX,BX            ;?flag=0
  255.         JZ    BRAN1            ;yes, so branch
  256.         INC    SI            ;point IP to next word
  257.         INC    SI
  258.         $NEXT
  259. BRAN1:        MOV    SI,0[SI]        ;IP:=(IP)
  260.         $NEXT
  261.  
  262. ;=C   branch    ( -- )
  263. ;        Branch to an inline address.
  264.  
  265.         $CODE    COMPO+6,branch,BRAN
  266.         MOV    SI,0[SI]        ;IP:=(IP)
  267.         $NEXT
  268.  
  269. ;=C   BYE    ( -- )
  270. ;        Exit eForth.
  271.  
  272.         $CODE    3,BYE,BYE
  273.         INT    20H            ;MS-DOS terminate process
  274.  
  275. ;=C   EXECUTE    ( ca -- )
  276. ;        Executes the word at ca.
  277.  
  278.         $CODE    7,EXECUTE,EXECU
  279.         POP    BX
  280.         JMP    BX            ;jump to the code address
  281.  
  282. ;=C   EXIT    ( -- )
  283. ;        Terminate current colon word.
  284.  
  285.         $CODE    4,EXIT,EXIT
  286.         MOV    SI,[BP]            ;pop return address
  287.         INC    BP            ;adjust RP
  288.         INC    BP
  289.         $NEXT
  290.  
  291. ;=C   !        ( w a -- )
  292. ;        Pop the data stack to memory.
  293.  
  294.         $CODE    1,!!!!,STORE
  295.         POP    BX
  296.         POP    0[BX]
  297.         $NEXT
  298.  
  299. ;=C   @        ( a -- w )
  300. ;        Push memory location to the data stack.
  301.  
  302.         $CODE    1,@,AT
  303.         POP    BX
  304.         PUSH    0[BX]
  305.         $NEXT
  306.  
  307. ;=C   C!    ( c b -- )
  308. ;        Pop the data stack to byte memory.
  309.  
  310.         $CODE    2,C!!!!,CSTOR
  311.         POP    BX
  312.         POP    AX
  313.         MOV    0[BX],AL
  314.         $NEXT
  315.  
  316. ;=C   C@    ( b -- c )
  317. ;        Push byte memory location to the data stack.
  318.  
  319.         $CODE    2,C@,CAT
  320.         POP    BX
  321.         XOR    AX,AX            ;AX=0 zero the hi byte
  322.         MOV    AL,0[BX]
  323.         PUSH    AX
  324.         $NEXT
  325.  
  326. ;=C   RP@    ( -- a )
  327. ;        Push the current RP to the data stack.
  328.  
  329.         $CODE    3,RP@,RPAT
  330.         PUSH    BP
  331.         $NEXT
  332.  
  333. ;=C   RP!    ( a -- )
  334. ;        Set the return stack pointer.
  335.  
  336.         $CODE    COMPO+3,RP!!!!,RPSTO
  337.         POP    BP
  338.         $NEXT
  339.  
  340. ;=C   R>    ( -- w )
  341. ;        Pop the return stack to the data stack.
  342.  
  343.         $CODE    COMPO+2,R!!!>,RFROM
  344.         PUSH    0[BP]
  345.         INC    BP            ;adjust RP
  346.         INC    BP
  347.         $NEXT
  348.  
  349. ;=C   R@    ( -- w )
  350. ;        Copy top of return stack to the data stack.
  351.  
  352.         $CODE    2,R@,RAT
  353.         PUSH    0[BP]
  354.         $NEXT
  355.  
  356. ;=C   >R    ( w -- )
  357. ;        Push the data stack to the return stack.
  358.  
  359.         $CODE    COMPO+2,!!!>R,TOR
  360.         DEC    BP            ;adjust RP
  361.         DEC    BP
  362.         POP    0[BP]            ;push
  363.         $NEXT
  364.  
  365. ;=C   SP@    ( -- a )
  366. ;        Push the current data stack pointer.
  367.  
  368.         $CODE    3,SP@,SPAT
  369.         MOV    BX,SP            ;use BX to index the data stack
  370.         PUSH    BX
  371.         $NEXT
  372.  
  373. ;=C   SP!    ( a -- )
  374. ;        Set the data stack pointer.
  375.  
  376.         $CODE    3,SP!!!!,SPSTO
  377.         POP    SP
  378.         $NEXT
  379.  
  380. ;=C   DROP    ( w -- )
  381. ;        Discard top stack item.
  382.  
  383.         $CODE    4,DROP,DROP
  384.         INC    SP            ;adjust SP
  385.         INC    SP
  386.         $NEXT
  387.  
  388. ;=C   DUP    ( w -- w w )
  389. ;        Duplicate the top stack item.
  390.  
  391.         $CODE    3,DUP,DUPP
  392.         MOV    BX,SP            ;use BX to index the data stack
  393.         PUSH    0[BX]
  394.         $NEXT
  395.  
  396. ;=C   SWAP    ( w1 w2 -- w2 w1 )
  397. ;        Exchange top two stack items.
  398.  
  399.         $CODE    4,SWAP,SWAP
  400.         POP    BX
  401.         POP    AX
  402.         PUSH    BX
  403.         PUSH    AX
  404.         $NEXT
  405.  
  406. ;=C   OVER    ( w1 w2 -- w1 w2 w1 )
  407. ;        Copy second stack item to top.
  408.  
  409.         $CODE    4,OVER,OVER
  410.         MOV    BX,SP            ;use BX to index the stack
  411.         PUSH    2[BX]
  412.         $NEXT
  413.  
  414. ;=C   0<    ( n -- t )
  415. ;        Return true if n is negative.
  416.  
  417.         $CODE    2,0!!!<,ZLESS
  418.         POP    AX
  419.         CWD                ;sign extend
  420.         PUSH    DX
  421.         $NEXT
  422.  
  423. ;=C   AND    ( w w -- w )
  424. ;        Bitwise AND.
  425.  
  426.         $CODE    3,AND,ANDD
  427.         POP    BX
  428.         POP    AX
  429.         AND    BX,AX
  430.         PUSH    BX
  431.         $NEXT
  432.  
  433. ;=C   OR    ( w w -- w )
  434. ;        Bitwise OR.
  435.  
  436.         $CODE    2,OR,ORR
  437.         POP    BX
  438.         POP    AX
  439.         OR    BX,AX
  440.         PUSH    BX
  441.         $NEXT
  442.  
  443. ;=C   XOR    ( w w -- w )
  444. ;        Bitwise exclusive OR.
  445.  
  446.         $CODE    3,XOR,XORR
  447.         POP    BX
  448.         POP    AX
  449.         XOR    BX,AX
  450.         PUSH    BX
  451.         $NEXT
  452.  
  453. ;=C   UM+    ( u u -- udsum )
  454. ;        Add two unsigned single numbers and return a double sum.
  455.  
  456.         $CODE    3,UM+,UPLUS
  457.         XOR    CX,CX            ;CX=0 initial carry flag
  458.         POP    BX
  459.         POP    AX
  460.         ADD    AX,BX
  461.         RCL    CX,1            ;get carry
  462.         PUSH    AX            ;push sum
  463.         PUSH    CX            ;push carry
  464.         $NEXT
  465.  
  466. ;; Device I/O
  467.  
  468. ;=C   ?RX    ( -- c T | F )
  469. ;        Return input character and true, or a false if no input.
  470.  
  471.         $CODE    3,?RX,QRX
  472.         XOR    BX,BX            ;BX=0 setup for false flag
  473.         MOV    DL,0FFH            ;input command
  474.         MOV    AH,6            ;MS-DOS Direct Console I/O
  475.         INT    21H
  476.         JZ    DQKE3            ;?key ready
  477.         OR    AL,AL            ;AL=0 if extended char
  478.         JNZ    DQKE1            ;?extended character code
  479.         INT    21H
  480.         MOV    BH,AL            ;extended code in msb
  481.         JMP    DQKE2
  482. DQKE1:        MOV    BL,AL
  483. DQKE2:        PUSH    BX            ;save character
  484.         MOV    BX,TRUEE        ;true flag
  485. DQKE3:        PUSH    BX
  486.         $NEXT
  487.  
  488. ;=C   TX!    ( c -- )
  489. ;        Send character c to the output device.
  490.  
  491.         $CODE    3,TX!!!!,STOTX
  492.         POP    DX            ;char in DL
  493.         CMP    DL,0FFH            ;0FFH is interpreted as input
  494.         JNZ    EMIT1            ;do NOT allow input
  495.         MOV    DL,32            ;change to blank
  496. EMIT1:        MOV    AH,6            ;MS-DOS Direct Console I/O
  497.         INT    021H            ;display character
  498.         $NEXT
  499.  
  500. ;=C   !IO    ( -- )
  501. ;        Initialize the serial I/O devices.
  502.  
  503.         $CODE    3,!!!!IO,STOIO
  504.         $NEXT
  505.  
  506. ;; User variables and system variables
  507.  
  508. ;=:   doVAR    ( -- a )
  509. ;        Run time routine of variable and CREATE area.
  510.  
  511.         $COLON    COMPO+5,doVAR,DOVAR
  512.         DW    RFROM,EXIT
  513.  
  514. ;=:   UP    ( -- a )
  515. ;        Pointer to the user area.
  516.  
  517.         $COLON    2,UP,UP
  518.         DW    DOVAR
  519.         DW    UPP
  520.  
  521. ;=:   doUSER    ( -- a )
  522. ;        Run time routine of user variables.
  523.  
  524.         $COLON    COMPO+6,doUSER,DOUSE
  525.         DW    RFROM,AT,UP,AT,PLUS,EXIT
  526.  
  527. ;=U   SP0    ( -- a )
  528. ;        Pointer to bottom of the data stack.
  529.  
  530.         $USER    3,SP0,SZERO
  531.  
  532. ;=U   RP0    ( -- a )
  533. ;        Pointer to bottom of the return stack.
  534.  
  535.         $USER    3,RP0,RZERO
  536.  
  537. ;=U   '?KEY    ( -- a )
  538. ;        Execution vector of ?KEY.
  539.  
  540.         $USER    5,!!!'?KEY,TQKEY,TICKY
  541.  
  542. ;=U   'eEMIT    ( -- a )
  543. ;        Execution vector of EMIT.
  544.  
  545.         $USER    5,!!!'EMIT,TEMIT,TICKY
  546.  
  547. ;=U   'EXPECT    ( -- a )
  548. ;        Execution vector of EXPECT.
  549.  
  550.         $USER    7,!!!'EXPECT,TEXPE,TICKY
  551.  
  552. ;=U   'TAP    ( -- a )
  553. ;        Execution vector of TAP.
  554.  
  555.         $USER    4,!!!'TAP,TTAP,TICKY
  556.  
  557. ;=U   'ECHO    ( -- a )
  558. ;        Execution vector of ECHO.
  559.  
  560.         $USER    5,!!!'ECHO,TECHO,TICKY
  561.  
  562. ;=U   'PROMPT    ( -- a )
  563. ;        Execution vector of PROMPT.
  564.  
  565.         $USER    7,!!!'PROMPT,TPROM,TICKY
  566.  
  567. ;=U   BASE    ( -- a )
  568. ;        Storage of the radix base for numeric I/O.
  569.  
  570.         $USER    4,BASE,BASE
  571.  
  572. ;=U   tmp    ( -- a )
  573. ;        A temporary storage location used in parse and find.
  574.  
  575.         $USER    COMPO+3,tmp,TEMP
  576.  
  577. ;=U   SPAN    ( -- a )
  578. ;        Hold character count received by EXPECT.
  579.  
  580.         $USER    4,SPAN,SPAN
  581.  
  582. ;=U   >IN    ( -- a )
  583. ;        Hold the character pointer while parsing input stream.
  584.  
  585.         $USER    3,!!!>IN,INN
  586.  
  587. ;=U   #TIB    ( -- a )
  588. ;        Hold the size of the terminal input buffer.
  589.  
  590.         $USER    4,#TIB,NTIB
  591.         _USER = _USER+CELLL        ;hold the base address of the terminal input buffer
  592.  
  593. ;=U   CSP    ( -- a )
  594. ;        Hold the stack pointer for error checking.
  595.  
  596.         $USER    3,CSP,CSP
  597.  
  598. ;=U   'EVAL    ( -- a )
  599. ;        Execution vector of EVAL.
  600.  
  601.         $USER    5,!!!'EVAL,TEVAL,TICKY
  602.  
  603. ;=U   'NUMBER    ( -- a )
  604. ;        Execution vector of NUMBER?.
  605.  
  606.         $USER    7,!!!'NUMBER,TNUMB,TICKY
  607.  
  608. ;=U   HLD    ( -- a )
  609. ;        Hold a pointer in building a numeric output string.
  610.  
  611.         $USER    3,HLD,HLD
  612.  
  613. ;=U   HANDLER    ( -- a )
  614. ;        Hold the return stack pointer for error handling.
  615.  
  616.         $USER    7,HANDLER,HANDL
  617.  
  618. ;=U   CONTEXT    ( -- a )
  619. ;        A area to specify vocabulary search order.
  620.  
  621.         $USER    7,CONTEXT,CNTXT
  622.         _USER = _USER+CELLL*VOCSS    ;vocabulary stack
  623.  
  624. ;=U   CURRENT    ( -- a )
  625. ;        Point to the vocabulary to be extended.
  626.  
  627.         $USER    7,CURRENT,CRRNT
  628.         _USER = _USER+CELLL        ;vocabulary link pointer
  629.  
  630. ;=U   CP    ( -- a )
  631. ;        Point to the top of the code dictionary.
  632.  
  633.         $USER    2,CP,CP
  634.  
  635. ;=U   NP    ( -- a )
  636. ;        Point to the bottom of the name dictionary.
  637.  
  638.         $USER    2,NP,NP
  639.  
  640. ;=U   last    ( -- a )
  641. ;        Point to the last name field in the name dictionary.
  642.  
  643.         $USER    4,LAST,LAST
  644.  
  645. ;=U   VOCABS    ( -- a )???remove use label to VOCABS
  646. ;        Array of vocabulary threads.
  647.  
  648.         $USER    6,VOCABS,VOCAB
  649.  
  650. ;; Common functions
  651.  
  652. ;=:   ?DUP    ( w -- w w | 0 )
  653. ;        Dup tos if its is not zero.
  654.  
  655.         $COLON    4,?DUP,QDUP
  656.         DW    DUPP
  657.         DW    QBRAN,QDUP1
  658.         DW    DUPP
  659. QDUP1:        DW    EXIT
  660.  
  661. ;=:   ROT    ( w1 w2 w3 -- w2 w3 w1 )
  662. ;        Rot 3rd item to top.
  663.  
  664.         $COLON    3,ROT,ROT
  665.         DW    TOR,SWAP,RFROM,SWAP,EXIT
  666.  
  667. ;=:   2DROP    ( w w -- )
  668. ;        Discard two items on stack.
  669.  
  670.         $COLON    5,2DROP,DDROP
  671.         DW    DROP,DROP,EXIT
  672.  
  673. ;=:   2DUP    ( w1 w2 -- w1 w2 w1 w2 )
  674. ;        Duplicate top two items.
  675.  
  676.         $COLON    4,2DUP,DDUP
  677.         DW    OVER,OVER,EXIT
  678.  
  679. ;=:   +        ( w w -- sum )
  680. ;        Add top two items.
  681.  
  682.         $COLON    1,+,PLUS
  683.         DW    UPLUS,DROP,EXIT
  684.  
  685. ;=:   NOT    ( w -- w )
  686. ;        One's complement of tos.
  687.  
  688.         $COLON    3,NOT,INVER
  689.         DW    DOLIT,-1,XORR,EXIT
  690.  
  691. ;=:   NEGATE    ( n -- -n )
  692. ;        Two's complement of tos.
  693.  
  694.         $COLON    6,NEGATE,NEGAT
  695.         DW    INVER,DOLIT,1,PLUS,EXIT
  696.  
  697. ;=:   DNEGATE    ( d -- -d )
  698. ;        Two's complement of top double.
  699.  
  700.         $COLON    7,DNEGATE,DNEGA
  701.         DW    INVER,TOR,INVER
  702.         DW    DOLIT,1,UPLUS
  703.         DW    RFROM,PLUS,EXIT
  704.  
  705. ;=:   -        ( n1 n2 -- n1-n2 )
  706. ;        Subtraction.
  707.  
  708.         $COLON    1,-,SUBB
  709.         DW    NEGAT,PLUS,EXIT
  710.  
  711. ;=:   ABS    ( n -- n )
  712. ;        Return the absolute value of n.
  713.  
  714.         $COLON    3,ABS,ABSS
  715.         DW    DUPP,ZLESS
  716.         DW    QBRAN,ABS1
  717.         DW    NEGAT
  718. ABS1:        DW    EXIT
  719.  
  720. ;=:   =        ( w w -- t )
  721. ;        Return true if top two are equal.
  722.  
  723.         $COLON    1,=,EQUAL
  724.         DW    XORR
  725.         DW    QBRAN,EQU1
  726.         DW    DOLIT,FALSS,EXIT
  727. EQU1:        DW    DOLIT,TRUEE,EXIT
  728.  
  729. ;=:   U<    ( u u -- t )
  730. ;        Unsigned compare of top two items.
  731.  
  732.         $COLON    2,U!!!<,ULESS
  733.         DW    DDUP,XORR,ZLESS
  734.         DW    QBRAN,ULES1
  735.         DW    SWAP,DROP,ZLESS,EXIT
  736. ULES1:        DW    SUBB,ZLESS,EXIT
  737.  
  738. ;=:   <        ( n1 n2 -- t )
  739. ;        Signed compare of top two items.
  740.  
  741.         $COLON    1,!!!<,LESS
  742.         DW    DDUP,XORR,ZLESS
  743.         DW    QBRAN,LESS1
  744.         DW    DROP,ZLESS,EXIT
  745. LESS1:        DW    SUBB,ZLESS,EXIT
  746.  
  747. ;=:   MAX    ( n n -- n )
  748. ;        Return the greater of two top stack items.
  749.  
  750.         $COLON    3,MAX,MAX
  751.         DW    DDUP,LESS
  752.         DW    QBRAN,MAX1
  753.         DW    SWAP
  754. MAX1:        DW    DROP,EXIT
  755.  
  756. ;=:   MIN    ( n n -- n )
  757. ;        Return the smaller of top two stack items.
  758.  
  759.         $COLON    3,MIN,MIN
  760.         DW    DDUP,SWAP,LESS
  761.         DW    QBRAN,MIN1
  762.         DW    SWAP
  763. MIN1:        DW    DROP,EXIT
  764.  
  765. ;=:   WITHIN    ( u ul uh -- t )
  766. ;        Return true if u is within the range of ul and uh.
  767.  
  768.         $COLON    6,WITHIN,WITHI
  769.         DW    OVER,SUBB,TOR        ;ul<=u<uh
  770.         DW    SUBB,RFROM,ULESS,EXIT
  771.  
  772. ;; Math functions
  773.  
  774. ; Divide
  775.  
  776. ;=:   UM/MOD    ( udl udh un -- ur uq )
  777. ;        Unsigned divide of a double by a single. Return mod and quotient.
  778.  
  779.         $COLON    6,UM/MOD,UMMOD
  780.         DW    DDUP,ULESS
  781.         DW    QBRAN,UMM4
  782.         DW    NEGAT,DOLIT,15,TOR
  783. UMM1:        DW    TOR,DUPP,UPLUS
  784.         DW    TOR,TOR,DUPP,UPLUS
  785.         DW    RFROM,PLUS,DUPP
  786.         DW    RFROM,RAT,SWAP,TOR
  787.         DW    UPLUS,RFROM,ORR
  788.         DW    QBRAN,UMM2
  789.         DW    TOR,DROP,DOLIT,1,PLUS,RFROM
  790.         DW    BRAN,UMM3
  791. UMM2:        DW    DROP
  792. UMM3:        DW    RFROM
  793.         DW    DONXT,UMM1
  794.         DW    DROP,SWAP,EXIT
  795. UMM4:        DW    DROP,DDROP
  796.         DW    DOLIT,-1,DUPP,EXIT
  797.  
  798. ;=:   M/MOD    ( d n -- r q )
  799. ;        Signed floored divide of double by single. Return mod and quotient.
  800.  
  801.         $COLON    5,M/MOD,MSMOD
  802.         DW    DUPP,ZLESS,DUPP,TOR
  803.         DW    QBRAN,MMOD1
  804.         DW    NEGAT,TOR,DNEGA,RFROM
  805. MMOD1:        DW    TOR,DUPP,ZLESS
  806.         DW    QBRAN,MMOD2
  807.         DW    RAT,PLUS
  808. MMOD2:        DW    RFROM,UMMOD,RFROM
  809.         DW    QBRAN,MMOD3
  810.         DW    SWAP,NEGAT,SWAP
  811. MMOD3:        DW    EXIT
  812.  
  813. ;=:   /MOD    ( n n -- r q )
  814. ;        Signed divide. Return mod and quotient.
  815.  
  816.         $COLON    4,/MOD,SLMOD
  817.         DW    OVER,ZLESS,SWAP,MSMOD,EXIT
  818.  
  819. ;=:   MOD    ( n n -- r )
  820. ;        Signed divide. Return mod only.
  821.  
  822.         $COLON    3,MOD,MODD
  823.         DW    SLMOD,DROP,EXIT
  824.  
  825. ;=:   /        ( n n -- q )
  826. ;        Signed divide. Return quotient only.
  827.  
  828.         $COLON    1,/,SLASH
  829.         DW    SLMOD,SWAP,DROP,EXIT
  830.  
  831. ; Multiply
  832.  
  833. ;=:   UM*    ( u u -- ud )
  834. ;        Unsigned multiply. Return double product.
  835.  
  836.         $COLON    3,UM*,UMSTA
  837.         DW    DOLIT,0,SWAP,DOLIT,15,TOR
  838. UMST1:        DW    DUPP,UPLUS,TOR,TOR
  839.         DW    DUPP,UPLUS,RFROM,PLUS,RFROM
  840.         DW    QBRAN,UMST2
  841.         DW    TOR,OVER,UPLUS,RFROM,PLUS
  842. UMST2:        DW    DONXT,UMST1
  843.         DW    ROT,DROP,EXIT
  844.  
  845. ;=:   *        ( n n -- n )
  846. ;        Signed multiply. Return single product.
  847.  
  848.         $COLON    1,*,STAR
  849.         DW    UMSTA,DROP,EXIT
  850.  
  851. ;=:   M*    ( n n -- d )
  852. ;        Signed multiply. Return double product.
  853.  
  854.         $COLON    2,M*,MSTAR
  855.         DW    DDUP,XORR,ZLESS,TOR
  856.         DW    ABSS,SWAP,ABSS,UMSTA
  857.         DW    RFROM
  858.         DW    QBRAN,MSTA1
  859.         DW    DNEGA
  860. MSTA1:        DW    EXIT
  861.  
  862. ;=:   */MOD    ( n1 n2 n3 -- r q )
  863. ;        Multiply n1 and n2, then divide by n3. Return mod and quotient.
  864.  
  865.         $COLON    5,*/MOD,SSMOD
  866.         DW    TOR,MSTAR,RFROM,MSMOD,EXIT
  867.  
  868. ;=:   */    ( n1 n2 n3 -- q )
  869. ;        Multiply n1 by n2, then divide by n3. Return quotient only.
  870.  
  871.         $COLON    2,*/,STASL
  872.         DW    SSMOD,SWAP,DROP,EXIT
  873.  
  874. ;; The text interpreter
  875.  
  876. ;=:   CELL+    ( a -- a )
  877. ;        Add cell size in byte to address.
  878.  
  879.         $COLON    5,CELL+,CELLP
  880.         DW    DOLIT,CELLL,PLUS,EXIT
  881.  
  882. ;=:   CELL-    ( a -- a )
  883. ;        Subtract cell size in byte from address.
  884.  
  885.         $COLON    5,CELL-,CELLM
  886.         DW    DOLIT,0-CELLL,PLUS,EXIT
  887.  
  888. ;=:   CELLS    ( n -- n )
  889. ;        Multiply tos by cell size in bytes.
  890.  
  891.         $COLON    5,CELLS,CELLS
  892.         DW    DOLIT,CELLL,STAR,EXIT
  893.  
  894. ;=:   BL    ( -- 32 )
  895. ;        Return 32, the blank character.
  896.  
  897.         $COLON    2,BL,BLANK
  898.         DW    DOLIT,32,EXIT
  899.  
  900. ;=:   >CHAR    ( c -- c )
  901. ;        Replace non-printable character by a period.
  902.  
  903.         $COLON    5,!!!>CHAR,TCHAR
  904.         DW    DOLIT,127,ANDD,DUPP
  905.         DW    DOLIT,127,BLANK,WITHI
  906.         DW    QBRAN,TCHA1
  907.         DW    DROP,DOLIT,'.'
  908. TCHA1:        DW    EXIT
  909.  
  910. ;=:   DEPTH    ( -- n )
  911. ;        Return the depth of the data stack.
  912.  
  913.         $COLON    5,DEPTH,DEPTH
  914.         DW    SPAT,SZERO,AT,SWAP,SUBB
  915.         DW    DOLIT,CELLL,SLASH,EXIT
  916.  
  917. ;=:   PICK    ( ... +n -- ... w )
  918. ;        Copy the nth stack item to tos.
  919.  
  920.         $COLON    4,PICK,PICK
  921.         DW    DOLIT,1,PLUS,CELLS
  922.         DW    SPAT,PLUS,AT,EXIT
  923.  
  924. ;; Memory access
  925.  
  926. ;=:   +!    ( n a -- )
  927. ;        Add n to the contents at address a.
  928.  
  929.         $COLON    2,+!!!!,PSTOR
  930.         DW    SWAP,OVER,AT,PLUS
  931.         DW    SWAP,STORE,EXIT
  932.  
  933. ;=:   2!    ( d a -- )
  934. ;        Store the double integer to address a.
  935.  
  936.         $COLON    2,2!!!!,DSTOR
  937.         DW    SWAP,OVER,STORE
  938.         DW    CELLP,STORE,EXIT
  939.  
  940. ;=:   2@    ( a -- d )
  941. ;        Fetch double integer from address a.
  942.  
  943.         $COLON    2,2@,DAT
  944.         DW    DUPP,CELLP,AT
  945.         DW    SWAP,AT,EXIT
  946.  
  947. ;=:   COUNT    ( b -- b +n )
  948. ;        Return count byte of a string and add 1 to byte address.
  949.  
  950.         $COLON    5,COUNT,COUNT
  951.         DW    DUPP,DOLIT,1,PLUS
  952.         DW    SWAP,CAT,EXIT
  953.  
  954. ;=:   HERE    ( -- a )
  955. ;        Return the top of the code dictionary.
  956.  
  957.         $COLON    4,HERE,HERE
  958.         DW    CP,AT,EXIT
  959.  
  960. ;=:   PAD    ( -- a )
  961. ;        Return the address of the text buffer above the code dictionary.
  962.  
  963.         $COLON    3,PAD,PAD
  964.         DW    HERE,DOLIT,80,PLUS,EXIT
  965.  
  966. ;=:   TIB    ( -- a )
  967. ;        Return the address of the terminal input buffer.
  968.  
  969.         $COLON    3,TIB,TIB
  970.         DW    NTIB,CELLP,AT,EXIT
  971.  
  972. ;=:   @EXECUTE    ( a -- )
  973. ;        Execute vector stored in address a.
  974.  
  975.         $COLON    8,@EXECUTE,ATEXE
  976.         DW    AT,QDUP            ;?address or zero
  977.         DW    QBRAN,EXE1
  978.         DW    EXECU            ;execute if non-zero
  979. EXE1:        DW    EXIT            ;do nothing if zero
  980.  
  981. ;=:   CMOVE    ( b1 b2 u -- )
  982. ;        Copy u bytes from b1 to b2.
  983.  
  984.         $COLON    5,CMOVE,CMOVE
  985.         DW    TOR
  986.         DW    BRAN,CMOV2
  987. CMOV1:        DW    TOR,DUPP,CAT
  988.         DW    RAT,CSTOR
  989.         DW    DOLIT,1,PLUS
  990.         DW    RFROM,DOLIT,1,PLUS
  991. CMOV2:        DW    DONXT,CMOV1
  992.         DW    DDROP,EXIT
  993.  
  994. ;=:   FILL    ( b u c -- )
  995. ;        Fill u bytes of character c to area beginning at b.
  996.  
  997.         $COLON    4,FILL,FILL
  998.         DW    SWAP,TOR,SWAP
  999.         DW    BRAN,FILL2
  1000. FILL1:        DW    DDUP,CSTOR,DOLIT,1,PLUS
  1001. FILL2:        DW    DONXT,FILL1
  1002.         DW    DDROP,EXIT
  1003.  
  1004. ;=:   -TRAILING    ( b u -- b u )
  1005. ;        Adjust the count to eliminate trailing white space.
  1006.  
  1007.         $COLON    9,-TRAILING,DTRAI
  1008.         DW    TOR
  1009.         DW    BRAN,DTRA2
  1010. DTRA1:        DW    BLANK,OVER,RAT,PLUS,CAT,LESS
  1011.         DW    QBRAN,DTRA2
  1012.         DW    RFROM,DOLIT,1,PLUS,EXIT
  1013. DTRA2:        DW    DONXT,DTRA1
  1014.         DW    DOLIT,0,EXIT
  1015.  
  1016. ;=:   ALIGNED    ( b -- a )
  1017. ;        Align address to the cell boundary.
  1018.  
  1019.         $COLON    7,ALIGNED,ALGND
  1020.         DW    DUPP,DOLIT,0,DOLIT,CELLL
  1021.         DW    UMMOD,DROP,DUPP
  1022.         DW    QBRAN,ALGN1
  1023.         DW    DOLIT,CELLL,SWAP,SUBB
  1024. ALGN1:        DW    PLUS,EXIT
  1025.  
  1026. ;=:   PACK$    ( b u a -- a )
  1027. ;        Build a counted string with u characters from b. Null fill.
  1028.  
  1029.         $COLON    5,PACK$,PACKS
  1030.         DW    ALGND,DUPP,TOR        ;strings only on cell boundary
  1031.         DW    OVER,DUPP,DOLIT,CELLL,MODD
  1032.         DW    SUBB,OVER,PLUS
  1033.         DW    DOLIT,0,SWAP,STORE    ;null fill cell
  1034.         DW    DDUP,CSTOR,DOLIT,1,PLUS    ;save count
  1035.         DW    SWAP,CMOVE,RFROM,EXIT    ;move string
  1036.  
  1037. ;; Numeric output, single precision
  1038.  
  1039. ;=:   DIGIT    ( u -- c )
  1040. ;        Convert digit u to a character.
  1041.  
  1042.         $COLON    5,DIGIT,DIGIT
  1043.         DW    DOLIT,9,OVER,LESS
  1044.         DW    DOLIT,7,ANDD,PLUS
  1045.         DW    DOLIT,48,PLUS,EXIT
  1046.  
  1047. ;=:   EXTRACT    ( n base -- n c )
  1048. ;        Extract the least significant digit from n.
  1049.  
  1050.         $COLON    7,EXTRACT,EXTRC
  1051.         DW    DOLIT,0,SWAP,UMMOD
  1052.         DW    SWAP,DIGIT,EXIT
  1053.  
  1054. ;=:   <#    ( -- )
  1055. ;        Initiate the numeric output process.
  1056.  
  1057.         $COLON    2,!!!<#,BDIGS
  1058.         DW    PAD,HLD,STORE,EXIT
  1059.  
  1060. ;=:   HOLD    ( c -- )
  1061. ;        Insert a character into the numeric output string.
  1062.  
  1063.         $COLON    4,HOLD,HOLD
  1064.         DW    HLD,AT,DOLIT,1,SUBB
  1065.         DW    DUPP,HLD,STORE,CSTOR,EXIT
  1066.  
  1067. ;=:   #        ( u -- u )
  1068. ;        Extract one digit from u and append the digit to output string.
  1069.  
  1070.         $COLON    1,#,DIG
  1071.         DW    BASE,AT,EXTRC,HOLD,EXIT
  1072.  
  1073. ;=:   #S    ( u -- 0 )
  1074. ;        Convert u until all digits are added to the output string.
  1075.  
  1076.         $COLON    2,#S,DIGS
  1077. DIGS1:        DW    DIG,DUPP
  1078.         DW    QBRAN,DIGS2
  1079.         DW    BRAN,DIGS1
  1080. DIGS2:        DW    EXIT
  1081.  
  1082. ;=:   SIGN    ( n -- )
  1083. ;        Add a minus sign to the numeric output string.
  1084.  
  1085.         $COLON    4,SIGN,SIGN
  1086.         DW    ZLESS
  1087.         DW    QBRAN,SIGN1
  1088.         DW    DOLIT,45,HOLD
  1089. SIGN1:        DW    EXIT
  1090.  
  1091. ;=:   #>    ( w -- b u )
  1092. ;        Prepare the output string to be TYPE'd.
  1093.  
  1094.         $COLON    2,#!!!>,EDIGS
  1095.         DW    DROP,HLD,AT
  1096.         DW    PAD,OVER,SUBB,EXIT
  1097.  
  1098. ;=:   str    ( w -- b u )
  1099. ;        Convert a signed integer to a numeric string.
  1100.  
  1101.         $COLON    3,str,STR
  1102.         DW    DUPP,TOR,ABSS
  1103.         DW    BDIGS,DIGS,RFROM
  1104.         DW    SIGN,EDIGS,EXIT
  1105.  
  1106. ;=:   HEX    ( -- )
  1107. ;        Use radix 16 as base for numeric conversions.
  1108.  
  1109.         $COLON    3,HEX,HEX
  1110.         DW    DOLIT,16,BASE,STORE,EXIT
  1111.  
  1112. ;=:   DECIMAL    ( -- )
  1113. ;        Use radix 10 as base for numeric conversions.
  1114.  
  1115.         $COLON    7,DECIMAL,DECIM
  1116.         DW    DOLIT,10,BASE,STORE,EXIT
  1117.  
  1118. ;; Numeric input, single precision
  1119.  
  1120. ;=:   DIGIT?    ( c base -- u t )
  1121. ;        Convert a character to its numeric value. A flag indicates success.
  1122.  
  1123.         $COLON    6,DIGIT?,DIGTQ
  1124.         DW    TOR,DOLIT,48,SUBB
  1125.         DW    DOLIT,9,OVER,LESS
  1126.         DW    QBRAN,DGTQ1
  1127.         DW    DOLIT,7,SUBB
  1128.         DW    DUPP,DOLIT,10,LESS,ORR
  1129. DGTQ1:        DW    DUPP,RFROM
  1130.         DW    ULESS,EXIT
  1131.  
  1132. ;=:   NUMBER?    ( a -- n T | a F )
  1133. ;        Convert a number string to integer. Push a flag on tos.
  1134.  
  1135.         $COLON    7,NUMBER?,NUMBQ
  1136.         DW    BASE,AT,TOR,DOLIT,0,OVER,COUNT
  1137.         DW    OVER,CAT,DOLIT,36,EQUAL
  1138.         DW    QBRAN,NUMQ1
  1139.         DW    HEX,SWAP,DOLIT,1,PLUS
  1140.         DW    SWAP,DOLIT,1,SUBB
  1141. NUMQ1:        DW    OVER,CAT,DOLIT,45,EQUAL,TOR
  1142.         DW    SWAP,RAT,SUBB,SWAP,RAT,PLUS,QDUP
  1143.         DW    QBRAN,NUMQ6
  1144.         DW    DOLIT,1,SUBB,TOR
  1145. NUMQ2:        DW    DUPP,TOR,CAT,BASE,AT,DIGTQ
  1146.         DW    QBRAN,NUMQ4
  1147.         DW    SWAP,BASE,AT,STAR,PLUS,RFROM
  1148.         DW    DOLIT,1,PLUS
  1149.         DW    DONXT,NUMQ2
  1150.         DW    RAT,SWAP,DROP
  1151.         DW    QBRAN,NUMQ3
  1152.         DW    NEGAT
  1153. NUMQ3:        DW    SWAP
  1154.         DW    BRAN,NUMQ5
  1155. NUMQ4:        DW    RFROM,RFROM,DDROP,DDROP,DOLIT,FALSS
  1156. NUMQ5:        DW    DUPP
  1157. NUMQ6:        DW    RFROM,DDROP
  1158.         DW    RFROM,BASE,STORE,EXIT
  1159.  
  1160. ;; Basic I/O
  1161.  
  1162. ;=:   ?KEY    ( -- c T | F )
  1163. ;        Return input character and true, or a false if no input.
  1164.  
  1165.         $COLON    4,?KEY,QKEY
  1166.         DW    TQKEY,ATEXE,EXIT
  1167.  
  1168. ;=:   KEY    ( -- c )
  1169. ;        Wait for and return an input character.
  1170.  
  1171.         $COLON    3,KEY,KEY
  1172. KEY1:        DW    QKEY
  1173.         DW    QBRAN,KEY1
  1174.         DW    EXIT
  1175.  
  1176. ;=:   EMIT    ( c -- )
  1177. ;        Send a character to the output device.
  1178.  
  1179.         $COLON    4,EMIT,EMIT
  1180.         DW    TEMIT,ATEXE,EXIT
  1181.  
  1182. ;=:   NUF?    ( -- t )
  1183. ;        Return false if no input, else pause and if CR return true.
  1184.  
  1185.         $COLON    4,NUF?,NUFQ
  1186.         DW    QKEY,DUPP
  1187.         DW    QBRAN,NUFQ1
  1188.         DW    DDROP,KEY,DOLIT,CRR,EQUAL
  1189. NUFQ1:        DW    EXIT
  1190.  
  1191. ;=:   PACE    ( -- )
  1192. ;        Send a pace character for the file downloading process.
  1193.  
  1194.         $COLON    4,PACE,PACE
  1195.         DW    DOLIT,11,EMIT,EXIT
  1196.  
  1197. ;=:   SPACE    ( -- )
  1198. ;        Send the blank character to the output device.
  1199.  
  1200.         $COLON    5,SPACE,SPACE
  1201.         DW    BLANK,EMIT,EXIT
  1202.  
  1203. ;=:   SPACES    ( +n -- )
  1204. ;        Send n spaces to the output device.
  1205.  
  1206.         $COLON    6,SPACES,SPACS
  1207.         DW    DOLIT,0,MAX,TOR
  1208.         DW    BRAN,CHAR2
  1209. CHAR1:        DW    SPACE
  1210. CHAR2:        DW    DONXT,CHAR1
  1211.         DW    EXIT
  1212.  
  1213. ;=:   TYPE    ( b u -- )
  1214. ;        Output u characters from b.
  1215.  
  1216.         $COLON    4,TYPE,TYPES
  1217.         DW    TOR
  1218.         DW    BRAN,TYPE2
  1219. TYPE1:        DW    DUPP,CAT,EMIT
  1220.         DW    DOLIT,1,PLUS
  1221. TYPE2:        DW    DONXT,TYPE1
  1222.         DW    DROP,EXIT
  1223.  
  1224. ;=:   CR    ( -- )
  1225. ;        Output a carriage return and a line feed.
  1226.  
  1227.         $COLON    2,CR,CR
  1228.         DW    DOLIT,CRR,EMIT
  1229.         DW    DOLIT,LF,EMIT,EXIT
  1230.  
  1231. ;=:   do$    ( -- a )
  1232. ;        Return the address of a compiled string.
  1233.  
  1234.         $COLON    COMPO+3,do$,DOSTR
  1235.         DW    RFROM,RAT,RFROM,COUNT,PLUS
  1236.         DW    ALGND,TOR,SWAP,TOR,EXIT
  1237.  
  1238. ;=:   $"|    ( -- a )
  1239. ;        Run time routine compiled by $". Return address of a compiled string.
  1240.  
  1241.         $COLON    COMPO+3,$!!!"|,STRQB
  1242.         DW    DOSTR,EXIT        ;force a call to do$
  1243.  
  1244. ;=:   ."|    ( -- )
  1245. ;        Run time routine of ." . Output a compiled string.
  1246.  
  1247.         $COLON    COMPO+3,.!!!"|,DOTQB
  1248.         DW    DOSTR,COUNT,TYPES,EXIT
  1249.  
  1250. ;=:   .R    ( n +n -- )
  1251. ;        Display an integer in a field of n columns, right justified.
  1252.  
  1253.         $COLON    2,.R,DOTR
  1254.         DW    TOR,STR,RFROM,OVER,SUBB
  1255.         DW    SPACS,TYPES,EXIT
  1256.  
  1257. ;=:   U.R    ( u +n -- )
  1258. ;        Display an unsigned integer in n column, right justified.
  1259.  
  1260.         $COLON    3,U.R,UDOTR
  1261.         DW    TOR,BDIGS,DIGS,EDIGS
  1262.         DW    RFROM,OVER,SUBB
  1263.         DW    SPACS,TYPES,EXIT
  1264.  
  1265. ;=:   U.    ( u -- )
  1266. ;        Display an unsigned integer in free format.
  1267.  
  1268.         $COLON    2,U.,UDOT
  1269.         DW    BDIGS,DIGS,EDIGS
  1270.         DW    SPACE,TYPES,EXIT
  1271.  
  1272. ;=:   .        ( w -- )
  1273. ;        Display an integer in free format, preceeded by a space.
  1274.  
  1275.         $COLON    1,.,DOT
  1276.         DW    BASE,AT,DOLIT,10,XORR    ;?decimal
  1277.         DW    QBRAN,DOT1
  1278.         DW    UDOT,EXIT        ;no, display unsigned
  1279. DOT1:        DW    STR,SPACE,TYPES,EXIT    ;yes, display signed
  1280.  
  1281. ;=:   ?        ( a -- )
  1282. ;        Display the contents in a memory cell.
  1283.  
  1284.         $COLON    1,?,QUEST
  1285.         DW    AT,DOT,EXIT
  1286.  
  1287. ;; Parsing
  1288.  
  1289. ;=:   parse    ( b u c -- b u delta ; <string> )
  1290. ;        Scan string delimited by c. Return found string and its offset.
  1291.  
  1292.         $COLON    5,parse,PARS
  1293.         DW    TEMP,STORE,OVER,TOR,DUPP
  1294.         DW    QBRAN,PARS8
  1295.         DW    DOLIT,1,SUBB,TEMP,AT,BLANK,EQUAL
  1296.         DW    QBRAN,PARS3
  1297.         DW    TOR
  1298. PARS1:        DW    BLANK,OVER,CAT        ;skip leading blanks ONLY
  1299.         DW    SUBB,ZLESS,INVER
  1300.         DW    QBRAN,PARS2
  1301.         DW    DOLIT,1,PLUS
  1302.         DW    DONXT,PARS1
  1303.         DW    RFROM,DROP,DOLIT,0,DUPP,EXIT
  1304. PARS2:        DW    RFROM
  1305. PARS3:        DW    OVER,SWAP
  1306.         DW    TOR
  1307. PARS4:        DW    TEMP,AT,OVER,CAT,SUBB    ;scan for delimiter
  1308.         DW    TEMP,AT,BLANK,EQUAL
  1309.         DW    QBRAN,PARS5
  1310.         DW    ZLESS
  1311. PARS5:        DW    QBRAN,PARS6
  1312.         DW    DOLIT,1,PLUS
  1313.         DW    DONXT,PARS4
  1314.         DW    DUPP,TOR
  1315.         DW    BRAN,PARS7
  1316. PARS6:        DW    RFROM,DROP,DUPP
  1317.         DW    DOLIT,1,PLUS,TOR
  1318. PARS7:        DW    OVER,SUBB
  1319.         DW    RFROM,RFROM,SUBB,EXIT
  1320. PARS8:        DW    OVER,RFROM,SUBB,EXIT
  1321.  
  1322. ;=:   PARSE    ( c -- b u ; <string> )
  1323. ;        Scan input stream and return counted string delimited by c.
  1324.  
  1325.         $COLON    5,PARSE,PARSE
  1326.         DW    TOR,TIB,INN,AT,PLUS    ;current input buffer pointer
  1327.         DW    NTIB,AT,INN,AT,SUBB    ;remaining count
  1328.         DW    RFROM,PARS,INN,PSTOR,EXIT
  1329.  
  1330. ;=:   .(    ( -- )
  1331. ;        Output following string up to next ) .
  1332.  
  1333.         $COLON    IMEDD+2,.(,DOTPR
  1334.         DW    DOLIT,41,PARSE,TYPES,EXIT
  1335.  
  1336. ;=:   (        ( -- )
  1337. ;        Ignore following string up to next ) . A comment.
  1338.  
  1339.         $COLON    IMEDD+1,(,PAREN
  1340.         DW    DOLIT,41,PARSE,DDROP,EXIT
  1341.  
  1342. ;=:   \        ( -- )
  1343. ;        Ignore following text till the end of line.
  1344.  
  1345.         $COLON    IMEDD+1,\,BKSLA
  1346.         DW    NTIB,AT,INN,STORE,EXIT
  1347.  
  1348. ;=:   CHAR    ( -- c )
  1349. ;        Parse next word and return its first character.
  1350.  
  1351.         $COLON    4,CHAR,CHAR
  1352.         DW    BLANK,PARSE,DROP,CAT,EXIT
  1353.  
  1354. ;=:   TOKEN    ( -- a ; <string> )
  1355. ;        Parse a word from input stream and copy it to name dictionary.
  1356.  
  1357.         $COLON    5,TOKEN,TOKEN
  1358.         DW    BLANK,PARSE,DOLIT,31,MIN
  1359.         DW    NP,AT,OVER,SUBB,CELLM
  1360.         DW    PACKS,EXIT
  1361.  
  1362. ;=:   WORD    ( c -- a ; <string> )
  1363. ;        Parse a word from input stream and copy it to code dictionary.
  1364.  
  1365.         $COLON    4,WORD,WORDD
  1366.         DW    PARSE,HERE,PACKS,EXIT
  1367.  
  1368. ;; Dictionary Search
  1369.  
  1370. ;=:   NAME>    ( na -- ca )
  1371. ;        Return code field address of a word from its name field address.
  1372.  
  1373.         $COLON    5,NAME!!!>,NAMET
  1374.         DW    CELLM,CELLM,AT,EXIT
  1375.  
  1376. ;=:   SAME?    ( a a u -- a a f \ -0+ )
  1377. ;        Compare u cells in two strings. Return 0 if identical.
  1378.  
  1379.         $COLON    5,SAME?,SAMEQ
  1380.         DW    TOR
  1381.         DW    BRAN,SAME2
  1382. SAME1:        DW    OVER,RAT,CELLS,PLUS,AT
  1383.         DW    OVER,RAT,CELLS,PLUS,AT
  1384.         DW    SUBB,QDUP
  1385.         DW    QBRAN,SAME2
  1386.         DW    RFROM,DROP,EXIT
  1387. SAME2:        DW    DONXT,SAME1
  1388.         DW    DOLIT,FALSS,EXIT
  1389.  
  1390. ;=:   find    ( a va -- ca na | a F )
  1391. ;        Search a vocabulary for a string. Return ca and na if succeeded.
  1392.  
  1393.         $COLON    4,find,FIND
  1394.         DW    SWAP,DUPP,CAT,DOLIT
  1395.         DW    CELLL,SLASH,TEMP,STORE
  1396.         DW    DUPP,AT,TOR,CELLP,SWAP
  1397. FIND1:        DW    AT,DUPP
  1398.         DW    QBRAN,FIND6
  1399.         DW    DUPP,AT,DOLIT,MASKK,ANDD,RAT,XORR
  1400.         DW    QBRAN,FIND2
  1401.         DW    CELLP,DOLIT,-1
  1402.         DW    BRAN,FIND3
  1403. FIND2:        DW    CELLP,TEMP,AT,SAMEQ
  1404. FIND3:        DW    BRAN,FIND4
  1405. FIND6:        DW    RFROM,DROP
  1406.         DW    SWAP,CELLM,SWAP,EXIT
  1407. FIND4:        DW    QBRAN,FIND5
  1408.         DW    CELLM,CELLM
  1409.         DW    BRAN,FIND1
  1410. FIND5:        DW    RFROM,DROP,SWAP,DROP
  1411.         DW    CELLM
  1412.         DW    DUPP,NAMET,SWAP,EXIT
  1413.  
  1414. ;=:   NAME?    ( a -- ca na | a F )
  1415. ;        Search all context vocabularies for a string.
  1416.  
  1417.         $COLON    5,NAME?,NAMEQ
  1418.         DW    CNTXT,DUPP,DAT,XORR
  1419.         DW    QBRAN,NAMQ1
  1420.         DW    CELLM
  1421. NAMQ1:        DW    TOR
  1422. NAMQ2:        DW    RFROM,CELLP,DUPP,TOR
  1423.         DW    AT,QDUP
  1424.         DW    QBRAN,NAMQ3
  1425.         DW    FIND,QDUP
  1426.         DW    QBRAN,NAMQ2
  1427.         DW    RFROM,DROP,EXIT
  1428. NAMQ3:        DW    RFROM,DROP
  1429.         DW    DOLIT,FALSS,EXIT
  1430.  
  1431. ;; Terminal response
  1432.  
  1433. ;=:   ^H    ( bot eot cur -- bot eot cur )
  1434. ;        Backup the cursor by one character.
  1435.  
  1436.         $COLON    2,!!!^H,BKSP
  1437.         DW    TOR,OVER,RFROM,SWAP,OVER,XORR
  1438.         DW    QBRAN,BACK1
  1439.         DW    DOLIT,BKSPP,TECHO,ATEXE,DOLIT,1,SUBB
  1440.         DW    BLANK,TECHO,ATEXE
  1441.         DW    DOLIT,BKSPP,TECHO,ATEXE
  1442. BACK1:        DW    EXIT
  1443.  
  1444. ;=:   TAP    ( bot eot cur c -- bot eot cur )
  1445. ;        Accept and echo the key stroke and bump the cursor.
  1446.  
  1447.         $COLON    3,TAP,TAP
  1448.         DW    DUPP,TECHO,ATEXE
  1449.         DW    OVER,CSTOR,DOLIT,1,PLUS,EXIT
  1450.  
  1451. ;=:   kTAP    ( bot eot cur c -- bot eot cur )
  1452. ;        Process a key stroke, CR or backspace.
  1453.  
  1454.         $COLON    4,kTAP,KTAP
  1455.         DW    DUPP,DOLIT,CRR,XORR
  1456.         DW    QBRAN,KTAP3
  1457.         DW    DOLIT,BKSPP,XORR
  1458.         DW    QBRAN,KTAP1
  1459.         DW    BLANK,TAP
  1460.         DW    BRAN,KTAP2
  1461. KTAP1:        DW    BKSP
  1462. KTAP2:        DW    EXIT
  1463. KTAP3:        DW    DROP
  1464.         DW    SWAP,DROP,DUPP,EXIT
  1465.  
  1466. ;=:   accept    ( b u -- b u )
  1467. ;        Accept characters to input buffer. Return with actual count.
  1468.  
  1469.         $COLON    6,accept,ACCEP
  1470.         DW    OVER,PLUS,OVER
  1471. ACCP1:        DW    DDUP,XORR
  1472.         DW    QBRAN,ACCP4
  1473.         DW    KEY,DUPP,BLANK,SUBB
  1474.         DW    DOLIT,95,ULESS
  1475.         DW    QBRAN,ACCP2
  1476.         DW    TAP
  1477.         DW    BRAN,ACCP3
  1478. ACCP2:        DW    TTAP,ATEXE
  1479. ACCP3:        DW    BRAN,ACCP1
  1480. ACCP4:        DW    DROP,OVER,SUBB,EXIT
  1481.  
  1482. ;=:   EXPECT    ( b u -- )
  1483. ;        Accept input stream and store count in SPAN.
  1484.  
  1485.         $COLON    6,EXPECT,EXPEC
  1486.         DW    TEXPE,ATEXE,SPAN,STORE,DROP,EXIT
  1487.  
  1488. ;=:   QUERY    ( -- )
  1489. ;        Accept input stream to terminal input buffer.
  1490.  
  1491.         $COLON    5,QUERY,QUERY
  1492.         DW    TIB,DOLIT,80,TEXPE,ATEXE,NTIB,STORE
  1493.         DW    DROP,DOLIT,0,INN,STORE,EXIT
  1494.  
  1495. ;; Error handling
  1496.  
  1497. ;=:   CATCH    ( ca -- 0 | err# )
  1498. ;        Execute word at ca and set up an error frame for it.
  1499.  
  1500.         $COLON    5,CATCH,CATCH
  1501.         DW    SPAT,TOR,HANDL,AT,TOR    ;save error frame
  1502.         DW    RPAT,HANDL,STORE,EXECU    ;execute
  1503.         DW    RFROM,HANDL,STORE    ;restore error frame
  1504.         DW    RFROM,DROP,DOLIT,0,EXIT    ;no error
  1505.  
  1506. ;=:   THROW    ( err# -- err# )
  1507. ;        Reset system to current local error frame an update error flag.
  1508.  
  1509.         $COLON    5,THROW,THROW
  1510.         DW    HANDL,AT,RPSTO        ;restore return stack
  1511.         DW    RFROM,HANDL,STORE    ;restore handler frame
  1512.         DW    RFROM,SWAP,TOR,SPSTO    ;restore data stack
  1513.         DW    DROP,RFROM,EXIT
  1514.  
  1515. ;=:   NULL$    ( -- a )
  1516. ;        Return address of a null string with zero count.
  1517.  
  1518.         $COLON    5,NULL$,NULLS
  1519.         DW    DOVAR            ;emulate CREATE
  1520.         DW    0
  1521.  
  1522. ;=:   ABORT    ( -- )
  1523. ;        Reset data stack and jump to QUIT.
  1524.  
  1525.         $COLON    5,ABORT,ABORT
  1526.         DW    NULLS,THROW
  1527.  
  1528. ;=:   abort"    ( f -- )
  1529. ;        Run time routine of ABORT" . Abort with a message.
  1530.  
  1531.         $COLON    COMPO+6,abort!!!",ABORQ
  1532.         DW    QBRAN,ABOR1        ;text flag
  1533.         DW    DOSTR,THROW        ;pass error string
  1534. ABOR1:        DW    DOSTR,DROP,EXIT        ;drop error
  1535.  
  1536. ;; Interpret
  1537.  
  1538. ;=:   $INTERPRET    ( a -- )
  1539. ;        Interpret a word. If failed, convert it to an integer.
  1540.  
  1541.         $COLON    10,$INTERPRET,INTER
  1542.         DW    NAMEQ,QDUP        ;?defined
  1543.         DW    QBRAN,INTE1
  1544.         DW    AT,DOLIT,COMPO,ANDD    ;?compile only lexicon bits
  1545.         DW    ABORQ
  1546.         DB    13,' compile only'
  1547.         DW    EXECU,EXIT        ;execute defined word
  1548. INTE1:        DW    TNUMB,ATEXE        ;convert a number
  1549.         DW    QBRAN,INTE2
  1550.         DW    EXIT
  1551. INTE2:        DW    THROW            ;error
  1552.  
  1553. ;=:   [        ( -- )
  1554. ;        Start the text interpreter.
  1555.  
  1556.         $COLON    IMEDD+1,[,LBRAC
  1557.         DW    DOLIT,INTER,TEVAL,STORE,EXIT
  1558.  
  1559. ;=:   .OK    ( -- )
  1560. ;        Display 'ok' only while interpreting.
  1561.  
  1562.         $COLON    3,.OK,DOTOK
  1563.         DW    DOLIT,INTER,TEVAL,AT,EQUAL
  1564.         DW    QBRAN,DOTO1
  1565.         DW    DOTQB
  1566.         DB    3,' ok'
  1567. DOTO1:        DW    CR,EXIT
  1568.  
  1569. ;=:   ?STACK    ( -- )
  1570. ;        Abort if the data stack underflows.
  1571.  
  1572.         $COLON    6,?STACK,QSTAC
  1573.         DW    DEPTH,ZLESS        ;check only for underflow
  1574.         DW    ABORQ
  1575.         DB    11,' underflow '
  1576.         DW    EXIT
  1577.  
  1578. ;=:   EVAL    ( -- )
  1579. ;        Interpret the input stream.
  1580.  
  1581.         $COLON    4,EVAL,EVAL
  1582. EVAL1:        DW    TOKEN,DUPP,CAT        ;?input stream empty
  1583.         DW    QBRAN,EVAL2
  1584.         DW    TEVAL,ATEXE,QSTAC    ;evaluate input, check stack
  1585.         DW    BRAN,EVAL1
  1586. EVAL2:        DW    DROP,TPROM,ATEXE,EXIT    ;prompt
  1587.  
  1588. ;; Shell
  1589.  
  1590. ;=:   PRESET    ( -- )
  1591. ;        Reset data stack pointer and the terminal input buffer.
  1592.  
  1593.         $COLON    6,PRESET,PRESE
  1594.         DW    SZERO,AT,SPSTO
  1595.         DW    DOLIT,TIBB,NTIB,CELLP,STORE,EXIT
  1596.  
  1597. ;=:   XIO    ( a a a -- )
  1598. ;        Reset the I/O vectors 'EXPECT, 'TAP, 'ECHO and 'PROMPT.
  1599.  
  1600.         $COLON    3,XIO,XIO
  1601.         DW    DOLIT,ACCEP,TEXPE,STORE,TTAP,STORE
  1602.         DW    TECHO,STORE,TPROM,STORE,EXIT
  1603.  
  1604. ;=:   FILE    ( -- )
  1605. ;        Select I/O vectors for file download.
  1606.  
  1607.         $COLON    4,FILE,FILE
  1608.         DW    DOLIT,PACE,DOLIT,DROP
  1609.         DW    DOLIT,KTAP,XIO,EXIT
  1610.  
  1611. ;=:   HAND    ( -- )
  1612. ;        Select I/O vectors for terminal interface.
  1613.  
  1614.         $COLON    4,HAND,HAND
  1615.         DW    DOLIT,DOTOK,TEMIT,AT
  1616.         DW    DOLIT,KTAP,XIO,EXIT
  1617.  
  1618. ;=:   I/O    ( -- a )
  1619. ;        Array to store default I/O vectors.
  1620.  
  1621.         $COLON    3,I/O,ISLO
  1622.         DW    DOVAR            ;emulate CREATE
  1623.         DW    QRX,STOTX        ;default I/O vectors
  1624.  
  1625. ;=:   CONSOLE    ( -- )
  1626. ;        Initiate terminal interface.
  1627.  
  1628.         $COLON    7,CONSOLE,CONSO
  1629.         DW    ISLO,DAT,TQKEY,DSTOR    ;restore default I/O device
  1630.         DW    HAND,EXIT        ;keyboard input
  1631.  
  1632. ;=:   QUIT    ( -- )
  1633. ;        Reset return stack pointer and start text interpreter.
  1634.  
  1635.         $COLON    4,QUIT,QUIT
  1636.         DW    RZERO,AT,RPSTO        ;reset return stack pointer
  1637. QUIT1:        DW    LBRAC            ;start interpretation
  1638. QUIT2:        DW    QUERY            ;get input
  1639.         DW    DOLIT,EVAL,CATCH,QDUP    ;evaluate input
  1640.         DW    QBRAN,QUIT2        ;continue till error
  1641.         DW    TPROM,AT,TOR        ;save input device
  1642.         DW    CONSO,NULLS,OVER,XORR    ;?display error message
  1643.         DW    QBRAN,QUIT3
  1644.         DW    SPACE,COUNT,TYPES    ;error message
  1645.         DW    DOTQB
  1646.         DB    3,' ? '            ;error prompt
  1647. QUIT3:        DW    RFROM,DOLIT,DOTOK,XORR    ;?file input
  1648.         DW    QBRAN,QUIT4
  1649.         DW    DOLIT,ERR,EMIT        ;file error, tell host
  1650. QUIT4:        DW    PRESE            ;some cleanup
  1651.         DW    BRAN,QUIT1
  1652.  
  1653. ;=:   '        ( -- ca )
  1654. ;        Search context vocabularies for the next word in input stream.
  1655.  
  1656.         $COLON    1,!!!',TICK,TICKY
  1657.         DW    TOKEN,NAMEQ        ;?defined
  1658.         DW    QBRAN,TICK1
  1659.         DW    EXIT            ;yes, return code address
  1660. TICK1:        DW    THROW            ;no, error
  1661.  
  1662. ;; The compiler
  1663.  
  1664. ;=:   ALLOT    ( n -- )
  1665. ;        Allocate n bytes to the code dictionary.
  1666.  
  1667.         $COLON    5,ALLOT,ALLOT
  1668.         DW    CP,PSTOR,EXIT        ;adjust code pointer
  1669.  
  1670. ;=:   ,        ( w -- )
  1671. ;        Compile an integer into the code dictionary.
  1672.  
  1673.         $COLON    1,!!!,,COMMA
  1674.         DW    HERE,DUPP,CELLP        ;cell boundary
  1675.         DW    CP,STORE,STORE,EXIT    ;adjust code pointer and compile
  1676.  
  1677. ;=:   [COMPILE]    ( -- ; <string> )
  1678. ;        Compile the next immediate word into code dictionary.
  1679.  
  1680.         $COLON    IMEDD+9,[COMPILE],BCOMP
  1681.         DW    TICK,COMMA,EXIT
  1682.  
  1683. ;=:   COMPILE    ( -- )
  1684. ;        Compile the next address in colon list to code dictionary.
  1685.  
  1686.         $COLON    COMPO+7,COMPILE,COMPI
  1687.         DW    RFROM,DUPP,AT,COMMA    ;compile address
  1688.         DW    CELLP,TOR,EXIT        ;adjust return address
  1689.  
  1690. ;=:   LITERAL    ( w -- )
  1691. ;        Compile tos to code dictionary as an integer literal.
  1692.  
  1693.         $COLON    IMEDD+7,LITERAL,LITER
  1694.         DW    COMPI,DOLIT,COMMA,EXIT
  1695.  
  1696. ;=:   $,"    ( -- )
  1697. ;        Compile a literal string up to next " .
  1698.  
  1699.         $COLON    3,$!!!,!!!",STRNG
  1700.         DW    DOLIT,34,WORDD,CAT    ;move string to code dictionary
  1701.         DW    DOLIT,1,PLUS,ALLOT,EXIT    ;adjust the code pointer
  1702.  
  1703. ;=:   RECURSE    ( -- )
  1704. ;        Make the current word available for compilation.
  1705.  
  1706.         $COLON    IMEDD+7,RECURSE,RECUR
  1707.         DW    LAST,AT,NAMET,COMMA,EXIT
  1708.  
  1709. ;; Structures
  1710.  
  1711. ;=:   FOR    ( -- a )
  1712. ;        Start a FOR-NEXT loop structure in a colon definition.
  1713.  
  1714.         $COLON    IMEDD+3,FOR,FOR
  1715.         DW    COMPI,TOR,HERE,EXIT
  1716.  
  1717. ;=:   BEGIN    ( -- a )
  1718. ;        Start an infinite or indefinite loop structure.
  1719.  
  1720.         $COLON    IMEDD+5,BEGIN,BEGIN
  1721.         DW    HERE,EXIT
  1722.  
  1723. ;=:   NEXT    ( a -- )
  1724. ;        Terminate a FOR-NEXT loop structure.
  1725.  
  1726.         $COLON    IMEDD+4,NEXT,NEXT
  1727.         DW    COMPI,DONXT,COMMA,EXIT
  1728.  
  1729. ;=:   UNTIL    ( a -- )
  1730. ;        Terminate a BEGIN-UNTIL indefinite loop structure.
  1731.  
  1732.         $COLON    IMEDD+5,UNTIL,UNTIL
  1733.         DW    COMPI,QBRAN,COMMA,EXIT
  1734.  
  1735. ;=:   AGAIN    ( a -- )
  1736. ;        Terminate a BEGIN-AGAIN infinite loop structure.
  1737.  
  1738.         $COLON    IMEDD+5,AGAIN,AGAIN
  1739.         DW    COMPI,BRAN,COMMA,EXIT
  1740.  
  1741. ;=:   IF    ( -- A )
  1742. ;        Begin a conditional branch structure.
  1743.  
  1744.         $COLON    IMEDD+2,IF,IFF
  1745.         DW    COMPI,QBRAN,HERE
  1746.         DW    DOLIT,0,COMMA,EXIT
  1747.  
  1748. ;=:   AHEAD    ( -- A )
  1749. ;        Compile a forward branch instruction.
  1750.  
  1751.         $COLON    IMEDD+5,AHEAD,AHEAD
  1752.         DW    COMPI,BRAN,HERE,DOLIT,0,COMMA,EXIT
  1753.  
  1754. ;=:   REPEAT    ( A a -- )
  1755. ;        Terminate a BEGIN-WHILE-REPEAT indefinite loop.
  1756.  
  1757.         $COLON    IMEDD+6,REPEAT,REPEA
  1758.         DW    AGAIN,HERE,SWAP,STORE,EXIT
  1759.  
  1760. ;=:   THEN    ( A -- )
  1761. ;        Terminate a conditional branch structure.
  1762.  
  1763.         $COLON    IMEDD+4,THEN,THENN
  1764.         DW    HERE,SWAP,STORE,EXIT
  1765.  
  1766. ;=:   AFT    ( a -- a A )
  1767. ;        Jump to THEN in a FOR-AFT-THEN-NEXT loop the first time through.
  1768.  
  1769.         $COLON    IMEDD+3,AFT,AFT
  1770.         DW    DROP,AHEAD,BEGIN,SWAP,EXIT
  1771.  
  1772. ;=:   ELSE    ( A -- A )
  1773. ;        Start the false clause in an IF-ELSE-THEN structure.
  1774.  
  1775.         $COLON    IMEDD+4,ELSE,ELSEE
  1776.         DW    AHEAD,SWAP,THENN,EXIT
  1777.  
  1778. ;=:   WHILE    ( a -- A a )
  1779. ;        Conditional branch out of a BEGIN-WHILE-REPEAT loop.
  1780.  
  1781.         $COLON    IMEDD+5,WHILE,WHILE
  1782.         DW    IFF,SWAP,EXIT
  1783.  
  1784. ;=:   ABORT"    ( -- ; <string> )
  1785. ;        Conditional abort with an error message.
  1786.  
  1787.         $COLON    IMEDD+6,ABORT!!!",ABRTQ
  1788.         DW    COMPI,ABORQ,STRNG,EXIT
  1789.  
  1790. ;=:   $"    ( -- ; <string> )
  1791. ;        Compile an inline string literal.
  1792.  
  1793.         $COLON    IMEDD+2,$!!!",SQUOT
  1794.         DW    COMPI,STRQB,STRNG,EXIT
  1795.  
  1796. ;=:   ."    ( -- ; <string> )
  1797. ;        Compile an inline string literal to be typed out at run time.
  1798.  
  1799.         $COLON    IMEDD+2,.!!!",DOTQ
  1800.         DW    COMPI,DOTQB,STRNG,EXIT
  1801.  
  1802. ;; Name Compiler
  1803.  
  1804. ;=:   ?UNIQUE    ( a -- a )
  1805. ;        Display a warning message if word at a exists in dictionary.
  1806.  
  1807.         $COLON    7,?UNIQUE,UNIQU
  1808.         DW    DUPP,NAMEQ        ;?name exists
  1809.         DW    QBRAN,UNIQ1
  1810.         DW    DOTQB            ;its OK to redefine a word
  1811.         DB    7,' reDef '        ;but the user should be warned
  1812.         DW    OVER,COUNT,TYPES    ;just in case its not planned
  1813. UNIQ1:        DW    DROP,EXIT
  1814.  
  1815. ;=:   $,n    ( na -- )
  1816. ;        Build a new dictionary name using the string at na.
  1817.  
  1818.         $COLON    3,$!!!,n,SNAME
  1819.         DW    DUPP,CAT        ;?null input
  1820.         DW    QBRAN,PNAM1
  1821.         DW    UNIQU            ;?redefinition
  1822.         DW    DUPP,LAST,STORE        ;save na for vocabulary link
  1823.         DW    HERE,ALGND,SWAP        ;align code address
  1824.         DW    CELLM            ;link address
  1825.         DW    CRRNT,AT,AT,OVER,STORE
  1826.         DW    CELLM,DUPP,NP,STORE    ;adjust name pointer
  1827.         DW    STORE,EXIT        ;save code pointer
  1828. PNAM1:        DW    STRQB
  1829.         DB    5,' name'        ;null input
  1830.         DW    THROW
  1831.  
  1832. ;; FORTH Compiler
  1833.  
  1834. ;=:   $COMPILE    ( a -- )
  1835. ;        Compile next word to code dictionary as a token or literal.
  1836.  
  1837.         $COLON    8,$COMPILE,SCOMP
  1838.         DW    NAMEQ,QDUP        ;?defined
  1839.         DW    QBRAN,SCOM3
  1840.         DW    AT,DOLIT,IMEDD,ANDD    ;?immediate
  1841.         DW    QBRAN,SCOM1
  1842.         DW    EXECU            ;its immediate, execute
  1843.         DW    BRAN,SCOM2
  1844. SCOM1:        DW    COMMA            ;its not immediate, compile
  1845. SCOM2:        DW    EXIT
  1846. SCOM3:        DW    TNUMB,ATEXE        ;try to convert to number
  1847.         DW    QBRAN,SCOM4
  1848.         DW    LITER,EXIT        ;compile number as integer
  1849. SCOM4:        DW    THROW            ;error
  1850.  
  1851. ;=:   OVERT    ( -- )
  1852. ;        Link a new word into the current vocabulary.
  1853.  
  1854.         $COLON    5,OVERT,OVERT
  1855.         DW    LAST,AT,CRRNT,AT,STORE,EXIT
  1856.  
  1857. ;=:   ;        ( -- )
  1858. ;        Terminate a colon definition.
  1859.  
  1860.         $COLON    IMEDD+COMPO+1,!!!;,SEMIS
  1861.         DW    COMPI,EXIT,LBRAC,OVERT,EXIT
  1862.  
  1863. ;=:   ]        ( -- )
  1864. ;        Start compiling the words in the input stream.
  1865.  
  1866.         $COLON    1,],RBRAC
  1867.         DW    DOLIT,SCOMP,TEVAL,STORE,EXIT
  1868.  
  1869. ;=:   call,    ( ca -- )
  1870. ;        Assemble a call instruction to ca.
  1871.  
  1872.         $COLON    5,call!!!,,CALLC
  1873.         DW    DOLIT,CALLL,COMMA,HERE    ;Direct Threaded Code
  1874.         DW    CELLP,SUBB,COMMA,EXIT    ;DTC 8086 relative call
  1875.  
  1876. ;=:   :        ( -- ; <string> )
  1877. ;        Start a new colon definition using next word as its name.
  1878.  
  1879.         $COLON    1,!!!:,COLON
  1880.         DW    TOKEN,SNAME,DOLIT,DOLST
  1881.         DW    CALLC,RBRAC,EXIT
  1882.  
  1883. ;=:   IMMEDIATE    ( -- )
  1884. ;        Make the last compiled word an immediate word.
  1885.  
  1886.         $COLON    9,IMMEDIATE,IMMED
  1887.         DW    DOLIT,IMEDD,LAST,AT,AT,ORR
  1888.         DW    LAST,AT,STORE,EXIT
  1889.  
  1890. ;; Defining Words
  1891.  
  1892. ;=:   USER    ( u -- ; <string> )
  1893. ;        Compile a new user variable.
  1894.  
  1895.         $COLON    4,USER,USER
  1896.         DW    TOKEN,SNAME,OVERT
  1897.         DW    DOLIT,DOLST,CALLC
  1898.         DW    DOLIT,DOUSE,COMMA
  1899.         DW    COMMA,EXIT
  1900.  
  1901. ;=:   CREATE    ( -- ; <string> )
  1902. ;        Compile a new array entry without allocating code space.
  1903.  
  1904.         $COLON    6,CREATE,CREAT
  1905.         DW    TOKEN,SNAME,OVERT
  1906.         DW    DOLIT,DOLST,CALLC
  1907.         DW    DOLIT,DOVAR,COMMA,EXIT
  1908.  
  1909. ;=:   VARIABLE    ( -- ; <string> )
  1910. ;        Compile a new variable initialized to 0.
  1911.  
  1912.         $COLON    8,VARIABLE,VARIA
  1913.         DW    CREAT,DOLIT,0,COMMA,EXIT
  1914.  
  1915. ;=:   FORTH    ( -- )???
  1916. ;        Make FORTH vocabulary the context vocabulary.
  1917.  
  1918.         $COLON    5,FORTH,FORTH
  1919.         DW    VOCAB,CNTXT,STORE,EXIT
  1920.  
  1921. ;; Tools
  1922.  
  1923. ;=:   _TYPE    ( b u -- )
  1924. ;        Display a string. Non-printing characters are replaced by periods.
  1925.  
  1926.         $COLON    5,_TYPE,UTYPE
  1927.         DW    TOR            ;start count down loop
  1928.         DW    BRAN,UTYP2        ;skip first pass
  1929. UTYP1:        DW    DUPP,CAT,TCHAR,EMIT    ;display only printable
  1930.         DW    DOLIT,1,PLUS        ;increment address
  1931. UTYP2:        DW    DONXT,UTYP1        ;loop till done
  1932.         DW    DROP,EXIT
  1933.  
  1934. ;=:   dm+    ( a u -- a )
  1935. ;        Dump u bytes from a, leaving a+u on the stack.
  1936.  
  1937.         $COLON    3,dm+,DUMPP
  1938.         DW    OVER,DOLIT,4,UDOTR    ;display address
  1939.         DW    SPACE,TOR        ;start count down loop
  1940.         DW    BRAN,PDUM2        ;skip first pass
  1941. PDUM1:        DW    DUPP,CAT,DOLIT,3,UDOTR    ;display numeric data
  1942.         DW    DOLIT,1,PLUS        ;increment address
  1943. PDUM2:        DW    DONXT,PDUM1        ;loop till done
  1944.         DW    EXIT
  1945.  
  1946. ;=:   DUMP    ( a u -- )
  1947. ;        Dump u bytes from a, in a formatted manner.
  1948.  
  1949.         $COLON    4,DUMP,DUMP
  1950.         DW    BASE,AT,TOR,HEX        ;save radix, set hex
  1951.         DW    DOLIT,16,SLASH        ;change count to lines
  1952.         DW    TOR            ;start count down loop
  1953. DUMP1:        DW    CR,DOLIT,16,DDUP,DUMPP    ;display numeric
  1954.         DW    ROT,ROT
  1955.         DW    DOLIT,2,SPACS,UTYPE    ;display printable characters
  1956.         DW    NUFQ,INVER        ;user control
  1957.         DW    QBRAN,DUMP2
  1958.         DW    DONXT,DUMP1        ;loop till done
  1959.         DW    BRAN,DUMP3
  1960. DUMP2:        DW    RFROM,DROP        ;cleanup loop stack, early exit
  1961. DUMP3:        DW    DROP,RFROM,BASE,STORE    ;restore radix
  1962.         DW    EXIT
  1963.  
  1964. ;=:   .S    ( ... -- ... )
  1965. ;        Display the contents of the data stack.
  1966.  
  1967.         $COLON    2,.S,DOTS
  1968.         DW    CR,DEPTH        ;stack depth
  1969.         DW    TOR            ;start count down loop
  1970.         DW    BRAN,DOTS2        ;skip first pass
  1971. DOTS1:        DW    RAT,PICK,DOT        ;index stack, display contents
  1972. DOTS2:        DW    DONXT,DOTS1        ;loop till done
  1973.         DW    DOTQB
  1974.         DB    5,' <sp '        ;user friendly
  1975.         DW    EXIT
  1976.  
  1977. ;=:   !CSP    ( -- )
  1978. ;        Save stack pointer in CSP for error checking.
  1979.  
  1980.         $COLON    4,!!!!CSP,STCSP
  1981.         DW    SPAT,CSP,STORE,EXIT    ;save pointer
  1982.  
  1983. ;=:   ?CSP    ( -- )
  1984. ;        Abort if stack pointer differs from that saved in CSP.
  1985.  
  1986.         $COLON    4,?CSP,QCSP
  1987.         DW    SPAT,CSP,AT,XORR    ;compare pointers
  1988.         DW    ABORQ            ;abort if different
  1989.         DB    11,'stack depth'
  1990.         DW    EXIT
  1991.  
  1992. ;=:   >NAME    ( ca -- na | F )
  1993. ;        Convert code address to a name address.
  1994.  
  1995.         $COLON    5,!!!>NAME,TNAME
  1996.         DW    CRRNT            ;vocabulary link
  1997. TNAM1:        DW    CELLP,AT,QDUP        ;check all vocabularies
  1998.         DW    QBRAN,TNAM4
  1999.         DW    DDUP
  2000. TNAM2:        DW    AT,DUPP            ;?last word in a vocabulary
  2001.         DW    QBRAN,TNAM3
  2002.         DW    DDUP,NAMET,XORR        ;compare
  2003.         DW    QBRAN,TNAM3
  2004.         DW    CELLM            ;continue with next word
  2005.         DW    BRAN,TNAM2
  2006. TNAM3:        DW    SWAP,DROP,QDUP
  2007.         DW    QBRAN,TNAM1
  2008.         DW    SWAP,DROP,SWAP,DROP,EXIT
  2009. TNAM4:        DW    DROP,DOLIT,FALSS,EXIT
  2010.  
  2011. ;=:   .ID    ( na -- )
  2012. ;        Display the name at address.
  2013.  
  2014.         $COLON    3,.ID,DOTID
  2015.         DW    QDUP            ;if zero no name
  2016.         DW    QBRAN,DOTI1
  2017.         DW    COUNT,DOLIT,1FH,ANDD    ;mask lexicon bits
  2018.         DW    UTYPE,EXIT        ;display name string
  2019. DOTI1:        DW    DOTQB
  2020.         DB    9,' {noName}'
  2021.         DW    EXIT
  2022.  
  2023. ;=:   SEE    ( -- ; <string> )
  2024. ;        A simple definition decompiler.
  2025.  
  2026.         $COLON    3,SEE,SEE
  2027.         DW    CR,TICK,CELLP        ;starting address
  2028. SEE1:        DW    CELLP,DUPP,AT,DUPP    ;?does it contain a zero
  2029.         DW    QBRAN,SEE2
  2030.         DW    TNAME            ;?is it a name
  2031. SEE2:        DW    QDUP            ;name address or zero
  2032.         DW    QBRAN,SEE3
  2033.         DW    SPACE,DOTID        ;display name
  2034.         DW    BRAN,SEE4
  2035. SEE3:        DW    DUPP,AT,UDOT        ;display number
  2036. SEE4:        DW    NUFQ            ;user control
  2037.         DW    QBRAN,SEE1
  2038.         DW    DROP,EXIT
  2039.  
  2040. ;=:   WORDS    ( -- )
  2041. ;        Display the word names in the context vocabulary.
  2042.  
  2043.         $COLON    5,WORDS,WORDS
  2044.         DW    CR,CNTXT,AT        ;only words in context
  2045. WORS1:        DW    AT,QDUP            ;?at end of list
  2046.         DW    QBRAN,WORS2
  2047.         DW    DUPP,SPACE,DOTID    ;display a name
  2048.         DW    CELLM,NUFQ        ;user pause or continue
  2049.         DW    QBRAN,WORS1
  2050.         DW    DROP
  2051. WORS2:        DW    EXIT
  2052.  
  2053. ;; Hardware reset
  2054.  
  2055. ;=:   VER    ( -- n )
  2056. ;        Return the version number of this implementation.
  2057.  
  2058.         $COLON    3,VER,VERSN
  2059.         DW    DOLIT,VER*256+EXT,EXIT
  2060.  
  2061. ;=:   hi    ( -- )
  2062. ;        Display the sign-on message of eForth.
  2063.  
  2064.         $COLON    2,hi,HI
  2065.         DW    STOIO,CR,DOTQB
  2066.         DB    11,'eForth v'
  2067.         DB    VER+48,46,EXT+48    ;version
  2068.         DW    CR,EXIT
  2069.  
  2070. ;=:   'BOOT    ( -- a )
  2071. ;        The application startup vector.
  2072.  
  2073.         $COLON    5,!!!'BOOT,TBOOT,TICKY
  2074.         DW    DOVAR
  2075.         DW    HI            ;application to boot
  2076.  
  2077. ;=:   COLD    ( -- )
  2078. ;        The hilevel cold start sequence.
  2079.  
  2080.         $COLON    4,COLD,COLD
  2081. COLD1:        DW    DOLIT,UZERO,DOLIT,UPP
  2082.         DW    DOLIT,ULAST-UZERO,CMOVE    ;initialize user area
  2083.         DW    PRESE            ;initialize data stack and TIB
  2084.         DW    TBOOT,ATEXE        ;application boot
  2085.         DW    QUIT,EXIT        ;start interpretation
  2086.  
  2087. ;====================================================================
  2088.  
  2089. LASTN        EQU    _NAME+4            ;last name address in name dictionary.
  2090.  
  2091. NTOP        EQU    _NAME-0            ;next available memory in name dictionary.
  2092. CTOP        EQU    $+0            ;next available memory in code dictionary.
  2093.  
  2094. MAIN        ENDS
  2095.  
  2096. END    ORIG
  2097.  
  2098. ;====================================================================
  2099.  
  2100.