| \ A powerful locals implementation |
\ A powerful locals implementation |
| |
|
| \ Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. |
\ Copyright (C) 1995,1996,1997,1998,2000,2003,2004,2005,2007 Free Software Foundation, Inc. |
| |
|
| \ This file is part of Gforth. |
\ This file is part of Gforth. |
| |
|
| |
|
| \ You should have received a copy of the GNU General Public License |
\ You should have received a copy of the GNU General Public License |
| \ along with this program; if not, write to the Free Software |
\ along with this program; if not, write to the Free Software |
| \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
\ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
| |
|
| |
|
| \ More documentation can be found in the manual and in |
\ More documentation can be found in the manual and in |
| |
|
| require search.fs |
require search.fs |
| require float.fs |
require float.fs |
| |
require extend.fs \ for case |
| |
|
| : compile-@local ( n -- ) \ gforth compile-fetch-local |
: compile-@local ( n -- ) \ gforth compile-fetch-local |
| case |
case |
| postpone laddr# @ lp-offset, ; |
postpone laddr# @ lp-offset, ; |
| |
|
| \ you may want to make comments in a locals definitions group: |
\ you may want to make comments in a locals definitions group: |
| ' \ alias \ ( -- ) \ core-ext,block-ext backslash |
' \ alias \ ( compilation 'ccc<newline>' -- ; run-time -- ) \ core-ext,block-ext backslash |
| \G Line comment: if @code{BLK} contains 0, parse and discard the remainder |
\G Comment till the end of the line if @code{BLK} contains 0 (i.e., |
| \G of the parse area. Otherwise, parse and discard all subsequent characters in the |
\G while not loading a block), parse and discard the remainder of the |
| \G parse area corresponding to the current line. |
\G parse area. Otherwise, parse and discard all subsequent characters |
| |
\G in the parse area corresponding to the current line. |
| immediate |
immediate |
| |
|
| ' ( alias ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ core,file paren |
' ( alias ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ core,file paren |
| \G Comment: parse and discard all subsequent characters in the parse |
\G Comment, usually till the next @code{)}: parse and discard all |
| \G area until ")" is encountered. During interactive input, an end-of-line |
\G subsequent characters in the parse area until ")" is |
| \G also acts as a comment terminator. For file input, it does not; if the |
\G encountered. During interactive input, an end-of-line also acts as |
| \G end-of-file is encountered whilst parsing for the ")" delimiter, Gforth |
\G a comment terminator. For file input, it does not; if the |
| \G will generate a warning. |
\G end-of-file is encountered whilst parsing for the ")" delimiter, |
| |
\G Gforth will generate a warning. |
| immediate |
immediate |
| |
|
| forth definitions |
forth definitions |
| |
also locals-types |
| |
|
| |
\ these "locals" are used for comparison in TO |
| |
|
| |
c: some-clocal 2drop |
| |
d: some-dlocal 2drop |
| |
f: some-flocal 2drop |
| |
w: some-wlocal 2drop |
| |
|
| \ the following gymnastics are for declaring locals without type specifier. |
\ the following gymnastics are for declaring locals without type specifier. |
| \ we exploit a feature of our dictionary: every wordlist |
\ we exploit a feature of our dictionary: every wordlist |
| \ So we create a vocabulary new-locals, that creates a 'w:' local named x |
\ So we create a vocabulary new-locals, that creates a 'w:' local named x |
| \ when it is asked if it contains x. |
\ when it is asked if it contains x. |
| |
|
| also locals-types |
|
| |
|
| : new-locals-find ( caddr u w -- nfa ) |
: new-locals-find ( caddr u w -- nfa ) |
| \ this is the find method of the new-locals vocabulary |
\ this is the find method of the new-locals vocabulary |
| \ make a new local with name caddr u; w is ignored |
\ make a new local with name caddr u; w is ignored |
| \ the returned nfa denotes a word that produces what W: produces |
\ the returned nfa denotes a word that produces what W: produces |
| \ !! do the whole thing without nextname |
\ !! do the whole thing without nextname |
| drop nextname |
drop nextname |
| ['] W: >name ; |
['] W: >head-noprim ; |
| |
|
| previous |
previous |
| |
|
| ' drop A, \ rehash method |
' drop A, \ rehash method |
| ' drop A, |
' drop A, |
| |
|
| slowvoc @ |
new-locals-map mappedwordlist Constant new-locals-wl |
| slowvoc on |
|
| vocabulary new-locals |
\ slowvoc @ |
| slowvoc ! |
\ slowvoc on |
| new-locals-map ' new-locals >body wordlist-map A! \ !! use special access words |
\ vocabulary new-locals |
| |
\ slowvoc ! |
| |
\ new-locals-map ' new-locals >body wordlist-map A! \ !! use special access words |
| |
|
| variable old-dpp |
variable old-dpp |
| |
|
| \ and now, finally, the user interface words |
\ and now, finally, the user interface words |
| : { ( -- lastxt wid 0 ) \ gforth open-brace |
: { ( -- latestxt wid 0 ) \ gforth open-brace |
| dp old-dpp ! |
dp old-dpp ! |
| locals-dp dpp ! |
locals-dp dpp ! |
| lastxt get-current |
latestxt get-current |
| also new-locals |
get-order new-locals-wl swap 1+ set-order |
| also locals definitions locals-types |
also locals definitions locals-types |
| 0 TO locals-wordlist |
0 TO locals-wordlist |
| 0 postpone [ ; immediate |
0 postpone [ ; immediate |
| |
|
| locals-types definitions |
locals-types definitions |
| |
|
| : } ( lastxt wid 0 a-addr1 xt1 ... -- ) \ gforth close-brace |
: } ( latestxt wid 0 a-addr1 xt1 ... -- ) \ gforth close-brace |
| \ ends locals definitions |
\ ends locals definitions |
| ] old-dpp @ dpp ! |
] old-dpp @ dpp ! |
| begin |
begin |
| : locals-:-hook ( sys -- sys addr xt n ) |
: locals-:-hook ( sys -- sys addr xt n ) |
| \ addr is the nfa of the defined word, xt its xt |
\ addr is the nfa of the defined word, xt its xt |
| DEFERS :-hook |
DEFERS :-hook |
| last @ lastcfa @ |
latest latestxt |
| clear-leave-stack |
clear-leave-stack |
| 0 locals-size ! |
0 locals-size ! |
| locals-buffer locals-dp ! |
locals-buffer locals-dp ! |
| 2drop |
2drop |
| endif ; |
endif ; |
| |
|
| : >definer ( xt -- definer ) |
: >definer ( xt -- definer ) \ gforth |
| \ this gives a unique identifier for the way the xt was defined |
\G @var{Definer} is a unique identifier for the way the @var{xt} |
| \ words defined with different does>-codes have different definers |
\G was defined. Words defined with different @code{does>}-codes |
| \ the definer can be used for comparison and in definer! |
\G have different definers. The definer can be used for |
| |
\G comparison and in @code{definer!}. |
| dup >does-code |
dup >does-code |
| ?dup-if |
?dup-if |
| nip 1 or |
nip 1 or |
| >code-address |
>code-address |
| then ; |
then ; |
| |
|
| : definer! ( definer xt -- ) |
: definer! ( definer xt -- ) \ gforth |
| \ gives the word represented by xt the behaviour associated with definer |
\G The word represented by @var{xt} changes its behaviour to the |
| |
\G behaviour associated with @var{definer}. |
| over 1 and if |
over 1 and if |
| swap [ 1 invert ] literal and does-code! |
swap [ 1 invert ] literal and does-code! |
| else |
else |
| -&32 throw |
-&32 throw |
| endif ; |
endif ; |
| :noname |
:noname |
| 0 0 0. 0.0e0 { c: clocal w: wlocal d: dlocal f: flocal } |
|
| comp' drop dup >definer |
comp' drop dup >definer |
| case |
case |
| [ ' locals-wordlist ] literal >definer \ value |
[ ' locals-wordlist ] literal >definer \ value |
| \ !! dependent on c: etc. being does>-defining words |
\ !! dependent on c: etc. being does>-defining words |
| \ this works, because >definer uses >does-code in this case, |
\ this works, because >definer uses >does-code in this case, |
| \ which produces a relocatable address |
\ which produces a relocatable address |
| [ comp' clocal drop >definer ] literal |
[ comp' some-clocal drop ] literal >definer |
| OF POSTPONE laddr# >body @ lp-offset, POSTPONE c! ENDOF |
OF POSTPONE laddr# >body @ lp-offset, POSTPONE c! ENDOF |
| [ comp' wlocal drop >definer ] literal |
[ comp' some-wlocal drop ] literal >definer |
| OF POSTPONE laddr# >body @ lp-offset, POSTPONE ! ENDOF |
OF POSTPONE laddr# >body @ lp-offset, POSTPONE ! ENDOF |
| [ comp' dlocal drop >definer ] literal |
[ comp' some-dlocal drop ] literal >definer |
| OF POSTPONE laddr# >body @ lp-offset, POSTPONE 2! ENDOF |
OF POSTPONE laddr# >body @ lp-offset, POSTPONE 2! ENDOF |
| [ comp' flocal drop >definer ] literal |
[ comp' some-flocal drop ] literal >definer |
| OF POSTPONE laddr# >body @ lp-offset, POSTPONE f! ENDOF |
OF POSTPONE laddr# >body @ lp-offset, POSTPONE f! ENDOF |
| -&32 throw |
-&32 throw |
| endcase ; |
endcase ; |
| interpret/compile: TO ( c|w|d|r "name" -- ) \ core-ext,local |
interpret/compile: TO ( c|w|d|r "name" -- ) \ core-ext,local |
| |
|
| : locals| |
: locals| ( ... "name ..." -- ) \ local-ext locals-bar |
| \ don't use 'locals|'! use '{'! A portable and free '{' |
\ don't use 'locals|'! use '{'! A portable and free '{' |
| \ implementation is compat/anslocals.fs |
\ implementation is compat/anslocals.fs |
| BEGIN |
BEGIN |
| name 2dup s" |" compare 0<> |
name 2dup s" |" str= 0= |
| WHILE |
WHILE |
| (local) |
(local) |
| REPEAT |
REPEAT |