| \ A powerful locals implementation |
\ A powerful locals implementation |
| |
|
| \ Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc. |
\ Copyright (C) 1995,1996,1997,1998,2000,2003,2004,2005,2007,2011 Free Software Foundation, Inc. |
| |
|
| \ This file is part of Gforth. |
\ This file is part of Gforth. |
| |
|
| \ Gforth is free software; you can redistribute it and/or |
\ Gforth is free software; you can redistribute it and/or |
| \ modify it under the terms of the GNU General Public License |
\ modify it under the terms of the GNU General Public License |
| \ as published by the Free Software Foundation; either version 2 |
\ as published by the Free Software Foundation, either version 3 |
| \ of the License, or (at your option) any later version. |
\ of the License, or (at your option) any later version. |
| |
|
| \ This program is distributed in the hope that it will be useful, |
\ This program is distributed in the hope that it will be useful, |
| \ GNU General Public License for more details. |
\ GNU General Public License for more details. |
| |
|
| \ 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, see http://www.gnu.org/licenses/. |
| \ 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 |
| ' locals >body wordlist-id ' locals-list >body ! |
' locals >body wordlist-id ' locals-list >body ! |
| slowvoc ! |
slowvoc ! |
| |
|
| create locals-buffer 1000 allot \ !! limited and unsafe |
variable locals-mem-list \ linked list of all locals name memory in |
| \ here the names of the local variables are stored |
0 locals-mem-list ! \ the current (outer-level) definition |
| \ we would have problems storing them at the normal dp |
|
| |
|
| variable locals-dp \ so here's the special dp for locals. |
: free-list ( addr -- ) |
| |
\ free all members of a linked list (link field is first) |
| |
begin |
| |
dup while |
| |
dup @ swap free throw |
| |
repeat |
| |
drop ; |
| |
|
| |
: prepend-list ( addr1 addr2 -- ) |
| |
\ addr1 is the address of a list element, addr2 is the address of |
| |
\ the cell containing the address of the first list element |
| |
2dup @ swap ! \ store link to next element |
| |
! ; \ store pointer to new first element |
| |
|
| : alignlp-w ( n1 -- n2 ) |
: alignlp-w ( n1 -- n2 ) |
| \ cell-align size and generate the corresponding code for aligning lp |
\ cell-align size and generate the corresponding code for aligning lp |
| \ warn if list is not a sublist of locals-list |
\ warn if list is not a sublist of locals-list |
| locals-list @ sub-list? 0= if |
locals-list @ sub-list? 0= if |
| \ !! print current position |
\ !! print current position |
| ." compiler was overly optimistic about locals at a BEGIN" cr |
>stderr ." compiler was overly optimistic about locals at a BEGIN" cr |
| \ !! print assumption and reality |
\ !! print assumption and reality |
| then ; |
then ; |
| |
|
| locals-size @ swap ! |
locals-size @ swap ! |
| postpone lp@ postpone c! ; |
postpone lp@ postpone c! ; |
| |
|
| : create-local ( " name" -- a-addr ) |
7 cells 32 + constant locals-name-size \ 32-char name + fields + wiggle room |
| \ defines the local "name"; the offset of the local shall be |
|
| \ stored in a-addr |
: create-local1 ( "name" -- a-addr ) |
| create |
create |
| immediate restrict |
immediate restrict |
| here 0 , ( place for the offset ) ; |
here 0 , ( place for the offset ) ; |
| |
|
| |
variable dict-execute-dp \ the special dp for DICT-EXECUTE |
| |
|
| |
0 value dict-execute-ude \ USABLE-DICTIONARY-END during DICT-EXECUTE |
| |
|
| |
: dict-execute1 ( ... addr1 addr2 xt -- ... ) |
| |
\ execute xt with HERE set to addr1 and USABLE-DICTIONARY-END set to addr2 |
| |
dict-execute-dp @ dp 2>r |
| |
dict-execute-ude ['] usable-dictionary-end defer@ 2>r |
| |
swap to dict-execute-ude |
| |
['] dict-execute-ude is usable-dictionary-end |
| |
swap to dict-execute-dp |
| |
dict-execute-dp dpp ! |
| |
catch |
| |
2r> is usable-dictionary-end to dict-execute-ude |
| |
2r> dpp ! dict-execute-dp ! |
| |
throw ; |
| |
|
| |
defer dict-execute ( ... addr1 addr2 xt -- ... ) |
| |
|
| |
:noname ( ... addr1 addr2 xt -- ... ) |
| |
\ first have a dummy routine, for SOME-CLOCAL etc. below |
| |
nip nip execute ; |
| |
is dict-execute |
| |
|
| |
: create-local ( " name" -- a-addr ) |
| |
\ defines the local "name"; the offset of the local shall be |
| |
\ stored in a-addr |
| |
locals-name-size allocate throw |
| |
dup locals-mem-list prepend-list |
| |
locals-name-size cell /string over + ['] create-local1 dict-execute ; |
| |
|
| |
variable locals-dp \ so here's the special dp for locals. |
| |
|
| : lp-offset ( n1 -- n2 ) |
: lp-offset ( n1 -- n2 ) |
| \ converts the offset from the frame start to an offset from lp and |
\ converts the offset from the frame start to an offset from lp and |
| \ i.e., the address of the local is lp+locals_size-offset |
\ i.e., the address of the local is lp+locals_size-offset |
| 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 |
| |
|
| |
' dict-execute1 is dict-execute \ now the real thing |
| |
|
| \ 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 |
| \ slowvoc ! |
\ slowvoc ! |
| \ new-locals-map ' new-locals >body wordlist-map A! \ !! use special access words |
\ new-locals-map ' new-locals >body wordlist-map A! \ !! use special access words |
| |
|
| 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 ! |
latestxt get-current |
| locals-dp dpp ! |
|
| lastxt get-current |
|
| get-order new-locals-wl swap 1+ set-order |
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 |
| |
|
| 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 ! |
] |
| begin |
begin |
| dup |
dup |
| while |
while |
| : 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-mem-list @ free-list |
| |
0 locals-mem-list ! |
| 0 locals-list ! |
0 locals-list ! |
| dead-code off |
dead-code off |
| defstart ; |
defstart ; |
| 2drop |
2drop |
| endif ; |
endif ; |
| |
|
| : >definer ( xt -- definer ) |
: >definer ( xt -- definer ) \ gforth |
| \G @var{Definer} is a unique identifier for the way the @var{xt} |
\G @var{Definer} is a unique identifier for the way the @var{xt} |
| \G was defined. Words defined with different @code{does>}-codes |
\G was defined. Words defined with different @code{does>}-codes |
| \G have different definers. The definer can be used for |
\G have different definers. The definer can be used for |
| >code-address |
>code-address |
| then ; |
then ; |
| |
|
| : definer! ( definer xt -- ) |
: definer! ( definer xt -- ) \ gforth |
| \G The word represented by @var{xt} changes its behaviour to the |
\G The word represented by @var{xt} changes its behaviour to the |
| \G behaviour associated with @var{definer}. |
\G behaviour associated with @var{definer}. |
| over 1 and if |
over 1 and if |
| -&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 |