: link>flags 2 + ; : immediate 81 last @ link>flags c! ; : \ 100 word drop ; immediate \ The above lines implement the words to allow for "\" comments \ All numbers are in hex at this point. \ DEFINE CELL SIZE : cellsize 4 ; : cellmask 3 ; : compsize 2 ; : compmask 1 ; \ BASIC STACK WORDS : rot 2 roll ; : over 1 pick ; : 2dup over over ; : 2drop drop drop ; : 2swap 3 roll 3 roll ; : 2over 3 pick 3 pick ; \ WORD HEADER ACCESSORS : >does 2 + ; : >body 4 + ; : name>xt dup c@ + 4 + 0 4 - and ; : link>name 3 + ; : link>xt link>name name>xt ; : link>does link>xt 2 + ; : link>body link>xt 4 + ; \ DEFINE BASIC WORD BUILDERS : source tib #tib @ ; \ : compile, , ; : ' 20 word find 0 = 0 = and ; : _does r> dup >r 2 + last @ link>does w! ; : _setjmp 0a last @ link>flags c! ; : literal 0 compile, compile, ; immediate last @ link>body dup @ swap 2 + w! \ Patch in address of _lit : postpone ' compile, ; immediate : ['] ' postpone literal ; immediate : [compile] ' postpone literal ['] compile, compile, ; immediate : does> [compile] _does [compile] exit ; immediate \ CONDITIONAL EXECUTION AND LOOPING : if ['] _jz compile, here 2 allot ; immediate : else ['] _jmp compile, here 2 + swap w! here 2 allot ; immediate : then here swap w! ; immediate : begin here ; immediate : until ['] _jz compile, compile, ; immediate : again ['] _jmp compile, compile, ; immediate : while ['] _jz compile, here 2 allot ; immediate : repeat ['] _jmp compile, here 2 + swap w! compile, ; immediate : do ['] _lit compile, here 2 allot ['] drop compile, ['] swap compile, ['] >r compile, ['] >r compile, here ; immediate : ?do ['] 2dup compile, ['] > compile, ['] _jz compile, here 2 allot ['] swap compile, ['] >r compile, ['] >r compile, here ; immediate \ : _loop r> swap r> + r> dup >r swap dup >r > 0 = swap >r ; : loop ['] _lit compile, 1 compile, ['] _loop compile, ['] _jz compile, compile, ['] r> compile, ['] r> compile, here swap w! ['] 2drop compile, ; immediate : +loop ['] _loop compile, ['] _jz compile, compile, ['] r> compile, ['] r> compile, here swap w! ['] 2drop compile, ; immediate : leave r> r> drop r> dup >r >r >r ; : i r> r> dup >r swap >r ; : j r> r> r> r> dup >r swap >r swap >r swap >r ; \ DEFINE >FLAGS AND >LINK : >flags begin 1 - dup c@ 80 and until ; : >link >flags 2 - ; \ DEFINE DEFER AND IS \ Change code pointer from varfunc to deferfunc : defer create last @ link>xt dup w@ 3 + swap w! ; : is state @ if [compile] >body ' >does postpone literal [compile] w! else >body ' >does w! then ; immediate \ REDEFINE REFILL AS A DEFERRED WORD ' refill defer refill is refill \ DEFINE "(" COMMENT WORD NOW THAT WE CAN LOOP : ( begin #tib @ >in @ ?do tib i + c@ 29 = if i 1 + >in ! r> r> drop drop exit then loop refill 0 = until ; immediate ( PAD AND PRINT SUPPORT ) create pad 100 allot create printptr 4 allot : _d2a dup 0a < if 30 else 57 then + ; : _a2d dup 30 < if drop 0 1 - else dup 39 > if dup 41 < if drop 0 1 - else dup 5a > if dup 61 < if drop 0 1 - else dup 7a > if drop 0 1 - else 57 - then then else 37 - then then else 30 - then then dup base @ < 0 = if drop 0 1 - then ; : c!-- dup >r c! r> 1 - ; : cprint printptr @ c! printptr @ 1 - printptr ! ; ( DOUBLE WORDS ) : s>d 0 pick 0 < ; : m* * s>d ; : um* * 0 ; : d+ drop 1 roll drop + s>d ; : d- drop 1 roll drop - s>d ; : d* drop 1 roll drop * s>d ; : d/ drop 1 roll drop / s>d ; : dmod drop 1 roll drop mod s>d ; : _u/ over over swap 1 rshift swap / dup + dup >r over * rot swap - swap < 1 + r> + ; : u/ over 0 < if _u/ else / then ; : ud/ drop 1 roll drop u/ 0 ; : _umod swap dup 1 rshift 2 pick mod dup + swap 1 and + swap mod ; : umod over 0 < if _umod else mod then ; : udmod drop 1 roll drop umod 0 ; ( CORE WORDS ) : +! dup @ rot + swap ! ; : /mod over over >r >r mod r> r> / ; : [ state 0 ! ; : ] state 1 ! ; : r@ r> r> dup >r swap >r ; : sm/rem >r 2dup r@ s>d d/ drop r> swap >r s>d dmod drop r> ; : um/mod >r 2dup r@ s>d ud/ drop r> swap >r s>d udmod drop r> ; : fm/mod over over xor 1 31 lshift and if sm/rem else sm/rem then ; ( TODO ) : */mod >r m* r> sm/rem ; : */ */mod swap drop ; : <# pad ff + printptr ! ; : hold cprint ; : # drop dup base @ umod _d2a cprint base @ u/ 0 ; : #s begin # over over or 0 = until ; : #> drop drop printptr @ 1 + dup pad 100 + swap - ; : sign 0 < if 2d hold then ; : abs dup 0 < if 0 swap - then ; : type 0 ?do dup c@ emit 1 + loop drop ; : ._ dup abs 0 <# #s rot sign #> type ; : . ._ 20 emit ; : >number dup 0 ?do >r dup c@ _a2d dup 0 < if drop r> leave else swap >r >r base @ 0 d* r> 0 d+ r> 1 + r> 1 - then loop ; : 0= 0 = ; : 0< 0 < ; : 1+ 1 + ; : 1- 1 - ; : 2! swap over ! cellsize + ! ; : 2* dup + ; : 2/ dup 80000000 and swap 1 rshift or ; : 2@ dup cellsize + @ swap @ ; : ?dup dup if dup then ; : aligned cellmask + 0 cellsize - and ; : align here aligned here - allot ; : bl 20 ; : c, here c! 1 allot ; : cell+ cellsize + ; : cells cellsize * ; : char+ 1 + ; : chars ; \ : count dup char+ swap c@ ; : char 20 word count 0= if drop 0 else c@ then ; : [char] char postpone literal ; immediate \ : constant create here ! cellsize allot does> @ ; : constant create , last @ link>xt dup w@ 3 - swap w! ; : cr 0a emit 0d emit ; : decimal 0a base ! ; : environment? drop drop 0 ; : fill swap >r swap r> 0 ?do 2dup c! 1 + loop 2drop ; : hex 10 base ! ; : invert 0 1 - xor ; : max 2dup < if swap then drop ; : min 2dup > if swap then drop ; \ : cmove >r swap r> 0 ?do 2dup c@ swap c! 1+ swap 1+ swap loop 2drop ; : cmove> >r swap r> dup >r 1- dup >r + swap r> + swap r> ?do 2dup c@ swap c! 1- swap 1- swap loop 2drop ; : move r> 2dup > if r> cmove else r> cmove> then ; : negate 0 swap - ; : recurse last @ , ; immediate : _lit" r> dup 1 + swap dup c@ dup rot + compsize + 0 compsize - and >r ; 84 last @ link>flags c! ( Set STRING flag ) : _compile" [char] " word count dup >r dup >r c, here r> cmove r> allot compsize here - compmask and allot ; immediate create s"buf 50 allot : s" state @ if ['] _lit" compile, postpone _compile" else [char] " word count >r s"buf r@ cmove s"buf r> then ; immediate : ." postpone s" ['] type compile, ; immediate : _abort" if type abort else drop drop then ; \ : abort" postpone s" ['] _abort" compile, ; immediate : abort" postpone s" ['] _abort" compile, ; : space 20 emit ; : spaces 0 ?do space loop ; : u._ 0 <# #s #> type ; : u. u._ 20 emit ; : u< over over xor 1 31 lshift and if swap then < ; : unloop r> r> r> drop drop >r ; : variable create cellsize allot ; ( CORE EXT ) : 0<> 0= invert ; : 0> 0 > ; : 2>r r> rot >r swap >r >r ; : 2r> r> r> r> rot >r swap ; : 2r@ r> r> r> 2dup >r >r swap rot >r ; : <> = 0= ; : erase 0 ?do dup 0 swap ! 1 + loop drop ; variable span : expect accept span ! ; : false 0 ; : marker create last @ , does> @ dup dp ! @ last ! ; : nip swap drop ; : parse word count ; : true 0 1 - ; : tuck swap over ; : to ' >body state @ if postpone literal [compile] ! else ! then ; immediate \ : value create here ! cellsize allot does> @ ; : value create , last @ link>xt dup w@ 3 - swap w! ; : within over - >r - r> u< ; : .r_ >r dup abs 0 <# #s rot sign #> dup r> swap - spaces type ; : .r .r_ 20 emit ; : u.r_ >r 0 <# #s #> dup r> swap - spaces type ; : u.r .r_ 20 emit ; : u> over over xor 80000000 and if swap then > ; : unused 8000 here - ; : case 0 ; immediate : of ['] over compile, ['] = compile, ['] _jz compile, here 4 allot ['] drop compile, ; immediate : endof ['] _jmp compile, here 2 + swap w! here 2 allot ; immediate : endcase ['] drop compile, begin ?dup while here swap w! repeat ; immediate : c" ['] _lit" compile, postpone _compile" ['] drop compile, ['] 1- compile, ; immediate : .( [char] ) word count type ; immediate : :noname align here ['] words @ , [ ; ( DOUBLE ) : d= rot = rot rot = and ; : d0= or 0 = ; : 2constant create swap , , does> dup @ swap cellsize + @ ; ( STRING ) : blank 0 ?do dup bl swap c! 1+ loop drop ; : -trailing dup 0 ?do 2dup + 1- c@ bl = if 1- else leave then loop ; : /string dup >r - swap r> + swap ; ( TOOLS ) : ? @ . ; : .s 3c emit depth ._ 3e emit 20 emit depth 0 ?do depth i - 1 - pick . loop ; : dump 0 ?do i 0f and 0 = if cr dup . then dup c@ 3 .r 1 + loop drop cr ; : forget 20 word find if >link dup dp ! w@ last ! else abort" ?" then ; : .name dup link>name count type space ; : ?newline dup >r link>name c@ dup rot + 1 + dup 4e > if cr else swap then drop r> ; : words 0 last @ begin dup while ?newline .name w@ repeat 2drop ; ( UTILITY ) : at-xy 2 emit swap emit emit ; : page 0 emit ; ( VERSION STRING ) : pfthversion s" pfth 1.03" ; create evalmode 0 , 0 value source-id create srcstk0 30 allot srcstk0 value srcstk : resetstack depth 0 < if begin depth while 0 repeat else begin depth while drop repeat then ; : getnumber 2dup >r >r swap dup c@ [char] - = if swap dup 1 < if 2drop 2drop r> r> 1 else swap 1 + swap 1 - >number dup if 2drop 2drop r> r> 1 else 2drop drop negate 0 r> r> 2drop then then else swap >number dup if 2drop 2drop r> r> 1 else 2drop drop 0 r> r> 2drop then then ; : compilenumber dup ['] _lit compile, compile, dup ffff 10 lshift and if 10 rshift ['] _lit compile, compile, ['] _lit compile, 10 compile, ['] lshift compile, ['] or compile, else drop then ; : _interpret begin 20 word dup c@ while find dup if state @ = if compile, else execute then else dup rot count getnumber if type ." ?" cr else state @ if compilenumber then then then repeat drop ; : .savesrc ." _savesrc " srcstk0 . srcstk . cr ; : .loadsrc ." _loadsrc " srcstk0 . srcstk . cr ; : _savesrc ( .savesrc ) tib srcstk ! #tib @ srcstk 4 + ! >in @ srcstk 8 + ! source-id srcstk 0c + ! srcstk 10 + to srcstk ; : _loadsrc srcstk 10 - to srcstk ( .loadsrc ) srcstk @ to tib srcstk 4 + @ #tib ! srcstk 8 + @ >in ! srcstk 0c + @ to source-id ; : evaluate _savesrc 0 1 - to source-id #tib ! to tib 0 >in ! _interpret _loadsrc ; ( INTERPRETER ) : interpret begin _interpret depth 0 < if ." Stack Underflow" cr resetstack else source-id 0 1 - = if _loadsrc \ 0 to source-id else source-id 0= if ." ok" cr then refill then then again ; decimal interpret