| \ tag: FCode implementation functions |
| \ |
| \ this code implements IEEE 1275-1994 ch. 5.3.3 |
| \ |
| \ Copyright (C) 2003 Stefan Reinauer |
| \ |
| \ See the file "COPYING" for further information about |
| \ the copyright and warranty status of this work. |
| \ |
| |
| hex |
| |
| 0 value fcode-sys-table \ table with built-in fcodes (0-0x7ff) |
| |
| true value ?fcode-offset16 \ fcode offsets are 16 instead of 8 bit? |
| 1 value fcode-spread \ fcode spread (1, 2 or 4) |
| 0 value fcode-table \ pointer to fcode table |
| false value ?fcode-verbose \ do verbose fcode execution? |
| |
| defer _fcode-debug? \ If true, save names for FCodes with headers |
| true value fcode-headers? \ If true, possibly save names for FCodes. |
| |
| 0 value fcode-stream-start \ start address of fcode stream |
| 0 value fcode-stream \ current fcode stream address |
| |
| variable fcode-end \ state variable, if true, fcode program terminates. |
| defer fcode-c@ \ get byte |
| |
| : fcode-push-state ( -- <state information> ) |
| ?fcode-offset16 |
| fcode-spread |
| fcode-table |
| fcode-headers? |
| fcode-stream-start |
| fcode-stream |
| fcode-end @ |
| ['] fcode-c@ behavior |
| ; |
| |
| : fcode-pop-state ( <state information> -- ) |
| to fcode-c@ |
| fcode-end ! |
| to fcode-stream |
| to fcode-stream-start |
| to fcode-headers? |
| to fcode-table |
| to fcode-spread |
| to ?fcode-offset16 |
| ; |
| |
| \ |
| \ fcode access helper functions |
| \ |
| |
| \ fcode-ptr |
| \ convert FCode number to pointer to xt in FCode table. |
| |
| : fcode-ptr ( u16 -- *xt ) |
| cells |
| fcode-table ?dup if + exit then |
| |
| \ we are not parsing fcode at the moment |
| dup 800 cells u>= abort" User FCODE# referenced." |
| fcode-sys-table + |
| ; |
| |
| \ fcode>xt |
| \ get xt according to an FCode# |
| |
| : fcode>xt ( u16 -- xt ) |
| fcode-ptr @ |
| ; |
| |
| \ fcode-num8 |
| \ get 8bit from FCode stream, taking spread into regard. |
| |
| : fcode-num8 ( -- c ) ( F: c -- ) |
| fcode-stream |
| dup fcode-spread + to fcode-stream |
| fcode-c@ |
| ; |
| |
| \ fcode-num8-signed ( -- c ) ( F: c -- ) |
| \ get 8bit signed from FCode stream |
| |
| : fcode-num8-signed |
| fcode-num8 |
| dup 80 and 0> if |
| ff invert or |
| then |
| ; |
| |
| \ fcode-num16 |
| \ get 16bit from FCode stream |
| |
| : fcode-num16 ( -- num16 ) |
| fcode-num8 fcode-num8 swap bwjoin |
| ; |
| |
| \ fcode-num16-signed ( -- c ) ( F: c -- ) |
| \ get 16bit signed from FCode stream |
| |
| : fcode-num16-signed |
| fcode-num16 |
| dup 8000 and 0> if |
| ffff invert or |
| then |
| ; |
| |
| \ fcode-num32 |
| \ get 32bit from FCode stream |
| |
| : fcode-num32 ( -- num32 ) |
| fcode-num8 fcode-num8 |
| fcode-num8 fcode-num8 |
| swap 2swap swap bljoin |
| ; |
| |
| \ fcode# |
| \ Get an FCode# from FCode stream |
| |
| : fcode# ( -- fcode# ) |
| fcode-num8 |
| dup 1 f between if |
| fcode-num8 swap bwjoin |
| then |
| ; |
| |
| \ fcode-offset |
| \ get offset from FCode stream. |
| |
| : fcode-offset ( -- offset ) |
| ?fcode-offset16 if |
| fcode-num16-signed |
| else |
| fcode-num8-signed |
| then |
| |
| \ Display offset in verbose mode |
| ?fcode-verbose if |
| dup ." (offset) " . cr |
| then |
| ; |
| |
| \ fcode-string |
| \ get a string from FCode stream, store in pocket. |
| |
| : fcode-string ( -- addr len ) |
| pocket dup |
| fcode-num8 |
| dup rot c! |
| 2dup bounds ?do |
| fcode-num8 i c! |
| loop |
| |
| \ Display string in verbose mode |
| ?fcode-verbose if |
| 2dup ." (const) " type cr |
| then |
| ; |
| |
| \ fcode-header |
| \ retrieve FCode header from FCode stream |
| |
| : fcode-header |
| fcode-num8 |
| fcode-num16 |
| fcode-num32 |
| ?fcode-verbose if |
| ." Found FCode header:" cr rot |
| ." Format : " u. cr swap |
| ." Checksum : " u. cr |
| ." Length : " u. cr |
| else |
| 3drop |
| then |
| \ TODO checksum |
| ; |
| |
| \ writes currently created word as fcode# read from stream |
| \ |
| |
| : fcode! ( F:FCode# -- ) |
| here fcode# |
| |
| \ Display fcode# in verbose mode |
| ?fcode-verbose if |
| dup ." (fcode#) " . cr |
| then |
| fcode-ptr ! |
| ; |
| |
| |
| \ |
| \ 5.3.3.1 Defining new FCode functions. |
| \ |
| |
| \ instance ( -- ) |
| \ Mark next defining word as instance specific. |
| \ (defined in bootstrap.fs) |
| |
| \ instance-init ( wid buffer -- ) |
| \ Copy template from specified wordlist to instance |
| \ |
| |
| : instance-init |
| swap |
| begin @ dup 0<> while |
| dup /n + @ instance-cfa? if \ buffer dict |
| 2dup 2 /n* + @ + \ buffer dict dest |
| over 3 /n* + @ \ buffer dict dest size |
| 2 pick 4 /n* + \ buffer dict dest size src |
| -rot |
| move |
| then |
| repeat |
| 2drop |
| ; |
| |
| |
| \ new-token ( F:/FCode#/ -- ) |
| \ Create a new unnamed FCode function |
| |
| : new-token |
| 0 0 header |
| fcode! |
| ; |
| |
| |
| \ named-token (F:FCode-string FCode#/ -- ) |
| \ Create a new possibly named FCode function. |
| |
| : named-token |
| fcode-string |
| _fcode-debug? not if |
| 2drop 0 0 |
| then |
| header |
| fcode! |
| ; |
| |
| |
| \ external-token (F:/FCode-string FCode#/ -- ) |
| \ Create a new named FCode function |
| |
| : external-token |
| fcode-string header |
| fcode! |
| ; |
| |
| |
| \ b(;) ( -- ) |
| \ End an FCode colon definition. |
| |
| : b(;) |
| ['] ; execute |
| ; immediate |
| |
| |
| \ b(:) ( -- ) ( E: ... -- ??? ) |
| \ Defines type of new FCode function as colon definition. |
| |
| : b(:) |
| 1 , ] |
| ; |
| |
| |
| \ b(buffer:) ( size -- ) ( E: -- a-addr ) |
| \ Defines type of new FCode function as buffer:. |
| |
| : b(buffer:) |
| 4 , allot |
| reveal |
| ; |
| |
| \ b(constant) ( nl -- ) ( E: -- nl ) |
| \ Defines type of new FCode function as constant. |
| |
| : b(constant) |
| 3 , , |
| reveal |
| ; |
| |
| |
| \ b(create) ( -- ) ( E: -- a-addr ) |
| \ Defines type of new FCode function as create word. |
| |
| : b(create) |
| 6 , |
| ['] noop , |
| reveal |
| ; |
| |
| |
| \ b(defer) ( -- ) ( E: ... -- ??? ) |
| \ Defines type of new FCode function as defer word. |
| |
| : b(defer) |
| 5 , |
| ['] (undefined-defer) , |
| ['] (semis) , |
| reveal |
| ; |
| |
| |
| \ b(field) ( offset size -- offset+size ) ( E: addr -- addr+offset ) |
| \ Defines type of new FCode function as field. |
| |
| : b(field) |
| 6 , |
| ['] noop , |
| reveal |
| over , |
| + |
| does> |
| @ + |
| ; |
| |
| |
| \ b(value) ( x -- ) (E: -- x ) |
| \ Defines type of new FCode function as value. |
| |
| : b(value) |
| 3 , , reveal |
| ; |
| |
| |
| \ b(variable) ( -- ) ( E: -- a-addr ) |
| \ Defines type of new FCode function as variable. |
| |
| : b(variable) |
| 4 , 0 , |
| reveal |
| ; |
| |
| |
| \ (is-user-word) ( name-str name-len xt -- ) ( E: ... -- ??? ) |
| \ Create a new named user interface command. |
| |
| : (is-user-word) |
| ; |
| |
| |
| \ get-token ( fcode# -- xt immediate? ) |
| \ Convert FCode number to function execution token. |
| |
| : get-token |
| fcode>xt dup immediate? |
| ; |
| |
| |
| \ set-token ( xt immediate? fcode# -- ) |
| \ Assign FCode number to existing function. |
| |
| : set-token |
| nip \ TODO we use the xt's immediate state for now. |
| fcode-ptr ! |
| ; |
| |
| |
| |
| |
| \ |
| \ 5.3.3.2 Literals |
| \ |
| |
| |
| \ b(lit) ( -- n1 ) |
| \ Numeric literal FCode. Followed by FCode-num32. |
| |
| 64bit? [IF] |
| : b(lit) |
| fcode-num32 32>64 |
| state @ if |
| ['] (lit) , , |
| then |
| ; immediate |
| [ELSE] |
| : b(lit) |
| fcode-num32 |
| state @ if |
| ['] (lit) , , |
| then |
| ; immediate |
| [THEN] |
| |
| |
| \ b(') ( -- xt ) |
| \ Function literal FCode. Followed by FCode# |
| |
| : b(') |
| fcode# fcode>xt |
| state @ if |
| ['] (lit) , , |
| then |
| ; immediate |
| |
| |
| \ b(") ( -- str len ) |
| \ String literal FCode. Followed by FCode-string. |
| |
| : b(") |
| fcode-string |
| state @ if |
| \ only run handle-text in compile-mode, |
| \ otherwise we would waste a pocket. |
| handle-text |
| then |
| ; immediate |
| |
| |
| \ |
| \ 5.3.3.3 Controlling values and defers |
| \ |
| |
| \ behavior ( defer-xt -- contents-xt ) |
| \ defined in bootstrap.fs |
| |
| \ b(to) ( new-value -- ) |
| \ FCode for setting values and defers. Followed by FCode#. |
| |
| : b(to) |
| fcode# fcode>xt |
| 1 handle-lit |
| ['] (to) |
| state @ if |
| , |
| else |
| execute |
| then |
| ; immediate |
| |
| |
| |
| \ |
| \ 5.3.3.4 Control flow |
| \ |
| |
| |
| \ offset16 ( -- ) |
| \ Makes subsequent FCode-offsets use 16-bit (not 8-bit) form. |
| |
| : offset16 |
| true to ?fcode-offset16 |
| ; |
| |
| |
| \ bbranch ( -- ) |
| \ Unconditional branch FCode. Followed by FCode-offset. |
| |
| : bbranch |
| fcode-offset 0< if \ if we jump backwards, we can forsee where it goes |
| ['] dobranch , |
| resolve-dest |
| execute-tmp-comp |
| else |
| setup-tmp-comp ['] dobranch , |
| here 0 |
| 0 , |
| 2swap |
| then |
| ; immediate |
| |
| |
| \ b?branch ( continue? -- ) |
| \ Conditional branch FCode. Followed by FCode-offset. |
| |
| : b?branch |
| fcode-offset 0< if \ if we jump backwards, we can forsee where it goes |
| ['] do?branch , |
| resolve-dest |
| execute-tmp-comp |
| else |
| setup-tmp-comp ['] do?branch , |
| here 0 |
| 0 , |
| then |
| ; immediate |
| |
| |
| \ b(<mark) ( -- ) |
| \ Target of backward branches. |
| |
| : b(<mark) |
| setup-tmp-comp |
| here 1 |
| ; immediate |
| |
| |
| \ b(>resolve) ( -- ) |
| \ Target of forward branches. |
| |
| : b(>resolve) |
| resolve-orig |
| execute-tmp-comp |
| ; immediate |
| |
| |
| \ b(loop) ( -- ) |
| \ End FCode do..loop. Followed by FCode-offset. |
| |
| : b(loop) |
| fcode-offset drop |
| postpone loop |
| ; immediate |
| |
| |
| \ b(+loop) ( delta -- ) |
| \ End FCode do..+loop. Followed by FCode-offset. |
| |
| : b(+loop) |
| fcode-offset drop |
| postpone +loop |
| ; immediate |
| |
| |
| \ b(do) ( limit start -- ) |
| \ Begin FCode do..loop. Followed by FCode-offset. |
| |
| : b(do) |
| fcode-offset drop |
| postpone do |
| ; immediate |
| |
| |
| \ b(?do) ( limit start -- ) |
| \ Begin FCode ?do..loop. Followed by FCode-offset. |
| |
| : b(?do) |
| fcode-offset drop |
| postpone ?do |
| ; immediate |
| |
| |
| \ b(leave) ( -- ) |
| \ Exit from a do..loop. |
| |
| : b(leave) |
| postpone leave |
| ; immediate |
| |
| |
| \ b(case) ( sel -- sel ) |
| \ Begin a case (multiple selection) statement. |
| |
| : b(case) |
| postpone case |
| ; immediate |
| |
| |
| \ b(endcase) ( sel | <nothing> -- ) |
| \ End a case (multiple selection) statement. |
| |
| : b(endcase) |
| postpone endcase |
| ; immediate |
| |
| |
| \ b(of) ( sel of-val -- sel | <nothing> ) |
| \ FCode for of in case statement. Followed by FCode-offset. |
| |
| : b(of) |
| fcode-offset drop |
| postpone of |
| ; immediate |
| |
| \ b(endof) ( -- ) |
| \ FCode for endof in case statement. Followed by FCode-offset. |
| |
| : b(endof) |
| fcode-offset drop |
| postpone endof |
| ; immediate |