:TYPEDUP 0> IF OVER + SWAP ?DO I C@ EMIT LOOP ELSE 2DROP THEN ;
:RSTR1+ DUP 2+ C@ 127AND TUCK - SWAP ;
:CR10EMIT ;
:SPACE32EMIT ;
:SPACESDUP 0> IF 0DO SPACE LOOP ELSE DROP THEN ;
:STR=0DO OVER C@ OVER C@ <>IF UNLOOP 2DROP FALSE EXIT THEN SWAP 1+ SWAP 1+ LOOP 2DROP TRUE ;
:IMMEDIATELATEST@ 1- DUP C@ 128OR SWAP C! ;
:HERE(here)@ ;
:[FALSE STATE ! ; IMMEDIATE
:]TRUE STATE ! ;
:ALLOT(here)+!;
:,HERE ! 2ALLOT ;
:C,HERE C! 1ALLOT ;
:SKIP-WHITEBEGIN DUP C@ 33< WHILE 1+ 2DUP =IF EXIT THEN REPEAT ;
:EXIT-IF-ENDSOURCE NIP >IN @ =IF SOURCE + 0R> DROP THEN ;
:PARSE-LIMITSSOURCE OVER + SWAP >IN @ + ;
:>IN-ENDSOURCE NIP >IN ! ;
:COUNTED-STRINGDUP HERE C! HERE 1+ -ROTOVER + SWAP DO I C@ OVER C! 1+ LOOP DROP HERE ;
:PARSE-WORDEXIT-IF-ENDPARSE-LIMITSSKIP-WHITE2DUP =IF >IN-ENDDROP 0EXIT THEN DUP >R BEGIN DUP C@ 32> WHILE 1+ 2DUP =IF >IN-ENDDROP R@ - R> SWAP EXIT THEN REPEAT NIP DUP SOURCE DROP - 1+ >IN ! R@ - R> SWAP ;
:PARSESOURCE NIP >IN @ =IF DROP SOURCE + 0EXIT THEN PARSE-LIMITSDUP >R ROT >R BEGIN DUP C@ R@ <>WHILE 1+ 2DUP =IF R> DROP >IN-ENDDROP R@ - R> SWAP EXIT THEN REPEAT R> DROP NIP DUP SOURCE DROP - 1+ >IN ! R@ - R> SWAP ;
\ TODO: Fix WORD not skipping leading delimiters
:WORDSOURCE NIP >IN @ =IF DROP 0HERE C! HERE EXIT THEN PARSE-LIMITSDUP >R ROT >R BEGIN DUP C@ R@ <>WHILE 1+ 2DUP =IF R> DROP >IN-ENDDROP R@ - R> SWAP EXIT THEN REPEAT R> DROP NIP DUP SOURCE DROP - 1+ >IN ! R@ - R> SWAP COUNTED-STRING;
:HEADERPARSE-WORDTUCK 0C, OVER + SWAP DO I C@ C, LOOP LATEST@ , C, ;
::HEADERHERE DUP LT! 42C, ];
::CODEHEADERHERE DUP LT! ;
:UNUSEDHERE NEGATE ;
:NCHARDUP C@ DUP 58< IF 48- ELSE DUP 97< IF 55- ELSE 87- THEN THEN ;
:>NUMBERDUP >R 0DO NCHARDUP BASE @ < OVER 0< INVERT AND IF 2SWAP BASE @ * 0SWAP ROT BASE @ UM* D+ ROT 0D+ ROT 1+ ELSE DROP I UNLOOP R> SWAP - EXIT THEN LOOP R> DROP 0;
:NONAME 002SWAP OVER C@ 45=IF SWAP 1+ SWAP 1- >NUMBER 2SWAP DROP NEGATE 12SWAP ELSE >NUMBER ROT DROP 1-ROTTHEN ; 'NUMBER!
:NUMBER'NUMBER@ EXECUTE ;
:SAVE-INPUT>IN @ 1;
:RESTORE-INPUTDUP 1=IF DROP >IN ! FALSE ELSE 0?DO DROP LOOP TRUE THEN ;
:COUNTDUP 1+ SWAP C@ ;
:CHARPARSE-WORDDROP C@ ;
:FILL-ROTDUP 0> IF OVER + SWAP DO DUP I C! LOOP ELSE 2DROP THEN DROP ;
:ERASE0FILL ;
:(41PARSE 2DROP ; IMMEDIATE
:.(41PARSE TYPE ; IMMEDIATE
:\10PARSE 2DROP ; IMMEDIATE
:THENHERE SWAP ! ; IMMEDIATE
:BEGINHERE ; IMMEDIATE
:FIND-WORD-DICOSWAP >R BEGIN DUP 4- RSTRR@ =IF 2PICK R@ STR=IF NIP R> DROP EXIT THEN ELSE DROP THEN 3- @ DUP 0= UNTIL NIP R> DROP ;
:GET-WL-LATESTDUP CW@ =IF DROP LATEST@ ELSE @ THEN ;
:FIND-WORDWORDERNWORDER@ 2* + WORDERDO I @ GET-WL-LATESTFIND-WORD-DICO?DUP IF UNLOOP EXIT THEN 2+LOOP 0;
:'PARSE-WORDFIND-WORD;
:POSTPONE'DUP 1- C@ 128AND IF , ELSE ['] (lit), , ['] , , THEN ; IMMEDIATE
:LITERAL['] (lit), , ; IMMEDIATE
:NLITERALDUP >R 0DO ['] (lit), 0, LOOP R> 0DO HERE 2- I 4* - ! LOOP ; IMMEDIATE
:ELSE['] (branch), HERE SWAP 0, HERE SWAP ! ; IMMEDIATE
:UNTIL['] (0branch), , ; IMMEDIATE
:REPEAT['] (branch), , HERE SWAP ! ; IMMEDIATE
:WHILE['] (0branch), HERE SWAP 0, ; IMMEDIATE
:CASE0; IMMEDIATE
:ENDCASE['] DROP , BEGIN DUP 0<> WHILE HERE SWAP ! REPEAT DROP ; IMMEDIATE
:OF['] OVER , ['] =, ['] (0branch), HERE 0, ['] DROP , ; IMMEDIATE
:ENDOF['] (branch), HERE 0, HERE ROT ! ; IMMEDIATE
\ : S" 34 PARSE ['] (branch) , HERE 0 , -ROT 2DUP OVER + SWAP ?DO I C@ C, LOOP NIP SWAP DUP HERE SWAP ! 2 + POSTPONE LITERAL POSTPONE LITERAL ; IMMEDIATE
:SLITERAL['] (slit), DUP , OVER + SWAP ?DO I C@ C, LOOP ; IMMEDIATE
:S"34PARSE POSTPONE SLITERAL ; IMMEDIATE
:PADHERE 36+ ;
:VALUEHEADERHERE LATEST! 77C, , 33C, 41C, ;
:TOPARSE-WORDFIND-WORD1+ STATE @ IF POSTPONE LITERAL ['] ! , ELSE ! THEN ; IMMEDIATE
:COMPILE,, ;
:AGAIN['] (branch), , ; IMMEDIATE
:ABORTEMPTYSQUIT ;
:COMPILE-WORD2DUP 2>R FIND-WORD?DUP IF 2R> 2DROP DUP 1- C@ 128AND IF EXECUTE ELSE , THEN ELSE 2R@ NUMBER0= IF DROP 2R> 2DROP POSTPONE NLITERALELSE DROP 0?DO DROP LOOP 2R> TYPE SPACE 63EMIT ABORT THEN THEN ;
:COUNTDUP 1+ SWAP C@ ;
:RECURSELT@ , ; IMMEDIATE
::NONAMEHERE DUP LT! 42C, LATEST@ ];
:>BODY7+ ;
:ENVIRONMENT?ENVDICO@ FIND-WORD-DICODUP IF EXECUTE TRUE THEN ;
:D0=OR 0= ;
:HOLDHERE @ 1- DUP HERE ! C! ;
:#BASE @ UDM/MODROT DUP 9> IF 55+ ELSE 48+ THEN HOLD ;
:#SBEGIN # 2DUP D0= UNTIL ;
:."POSTPONE S"['] TYPE , ; IMMEDIATE
:C"34PARSE ['] (branch), HERE 0, -ROTHERE -ROTDUP C, OVER + SWAP ?DO I C@ C, LOOP SWAP HERE SWAP ! POSTPONE LITERAL ; IMMEDIATE
:<#PAD HERE ! ;
:#>2DROP HERE @ PAD OVER - ;
:SIGN0< IF 45HOLD THEN ;
:CONVERT-1>NUMBER DROP ;
:MOVEDUP 0= IF DROP 2DROP EXIT THEN -ROT2DUP U> IF ROT 0DO OVER C@ OVER C! 1+ SWAP 1+ SWAP LOOP ELSE 2PICK TUCK + -ROT+ SWAP ROT 0DO 1- SWAP 1- SWAP OVER C@ OVER C! LOOP THEN 2DROP ;
:.DUP >R ABS 0<# BL HOLD #S R> SIGN #> TYPE ;
:U.0<# BL HOLD #S #> TYPE ;
:.R>R DUP >R ABS 0<# BL HOLD #S R> SIGN #> R> OVER - SPACES TYPE ;
:U.R>R 0<# BL HOLD #S #> R> OVER - SPACES TYPE ;
:WITHINOVER - >R - R> U< ;
:DO['] (do), HERE 0, HERE ; IMMEDIATE
:?DO['] (?do), HERE 0, HERE ; IMMEDIATE
:LOOP['] (loop), , HERE SWAP ! ; IMMEDIATE
:+LOOP['] (+loop), , HERE SWAP ! ; IMMEDIATE
:ACCEPTS"screen"DELETE-MSGBEGIN S"screen"16RECEIVE-ATDUP 0< WHILE DROP WAITREPEAT MIN TUCK 16-ROTMOVE ;
:EXPECTACCEPT SPAN ! ;
:QUERY0>IN ! 0SOURCE-ID ! TIB DUP 80ACCEPT SPACE (source)2! ;
:REFILLSOURCE-ID @ IF FALSE ELSE 0>IN ! TIB DUP 80ACCEPT SPACE (source)2! TRUE THEN ;
:INTERPRET-WORD2DUP 2>R FIND-WORD?DUP IF 2R> 2DROP EXECUTE ELSE 2R@ NUMBER0= IF 2DROP 2R> 2DROP ELSE DROP 0?DO DROP LOOP 2R> TYPE SPACE 63EMIT ABORT THEN THEN ;
:EVALUATESOURCE 2>R >IN @ >R SOURCE-ID @ >R -1SOURCE-ID ! 0>IN ! (source)2! BEGIN PARSE-WORD?DUP WHILE STATE @ IF COMPILE-WORDELSE INTERPRET-WORDTHEN REPEAT DROP R> SOURCE-ID ! R> >IN ! 2R> (source)2! ;
:QUITEMPTYRCR BEGIN REFILL WHILE BEGIN PARSE-WORD?DUP WHILE STATE @ IF COMPILE-WORDELSE INTERPRET-WORDTHEN REPEAT DROP SPACE 79EMIT 75EMIT CR REPEAT ;
:(abort")ROT IF TYPE ABORT THEN 2DROP ;
:ABORT"POSTPONE S"['] (abort"), ; IMMEDIATE
:DABSDUP 0< IF OVER NEGATE ROT IF SWAP INVERT ELSE SWAP NEGATE THEN THEN ;
:GET-LIST-ADDR>R BEGIN R@ C@ WHILE R@R@ 1+ @ R@ C@ SWAP >R TAG-LIST=IF 4+ IS-ADDR-LISTIF R> DROP DROP DROP DROP DROP R> -1EXIT THEN THEN R> R> DROP >R REPEAT R> DROP DROP DROP DROP DROP 0;