version 1.54, 2004/09/17 14:53:28
|
version 1.66, 2012/02/07 18:15:27
|
Line 1
|
Line 1
|
\ A powerful locals implementation |
\ A powerful locals implementation |
|
|
\ Copyright (C) 1995,1996,1997,1998,2000,2003 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, |
Line 15
|
Line 15
|
\ 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 |
Line 133 vocabulary locals \ this contains the lo
|
Line 132 vocabulary locals \ this contains the lo
|
' 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 |
Line 160 variable locals-dp \ so here's the speci
|
Line 170 variable locals-dp \ so here's the speci
|
|
|
\ locals list operations |
\ locals list operations |
|
|
: common-list ( list1 list2 -- list3 ) \ gforth-internal |
: list-length ( list -- u ) |
\ list1 and list2 are lists, where the heads are at higher addresses than |
0 swap begin ( u1 list1 ) |
\ the tail. list3 is the largest sublist of both lists. |
dup while |
begin |
@ swap 1+ swap |
2dup u<> |
repeat |
while |
drop ; |
2dup u> |
|
if |
: /list ( list1 u -- list2 ) |
swap |
\ list2 is list1 with the first u elements removed |
then |
0 ?do |
@ |
@ |
repeat |
loop ; |
drop ; |
|
|
: common-list ( list1 list2 -- list3 ) |
: sub-list? ( list1 list2 -- f ) \ gforth-internal |
\ list3 is the largest common tail of both lists. |
\ true iff list1 is a sublist of list2 |
over list-length over list-length - dup 0< if |
begin |
negate >r swap r> |
2dup u< |
then ( long short u ) |
while |
rot swap /list begin ( list3 list4 ) |
@ |
2dup u<> while |
repeat |
@ swap @ |
= ; |
repeat |
|
drop ; |
|
|
|
: sub-list? ( list1 list2 -- f ) |
|
\ true iff list1 is a sublist of list2 |
|
over list-length over list-length swap - 0 max /list = ; |
|
|
|
\ : ocommon-list ( list1 list2 -- list3 ) \ gforth-internal |
|
\ \ list1 and list2 are lists, where the heads are at higher addresses than |
|
\ \ the tail. list3 is the largest sublist of both lists. |
|
\ begin |
|
\ 2dup u<> |
|
\ while |
|
\ 2dup u> |
|
\ if |
|
\ swap |
|
\ then |
|
\ @ |
|
\ repeat |
|
\ drop ; |
|
|
|
\ : osub-list? ( list1 list2 -- f ) \ gforth-internal |
|
\ \ true iff list1 is a sublist of list2 |
|
\ begin |
|
\ 2dup u< |
|
\ while |
|
\ @ |
|
\ repeat |
|
\ = ; |
|
|
|
\ defer common-list |
|
\ defer sub-list? |
|
|
|
\ ' ocommon-list is common-list |
|
\ ' osub-list? is sub-list? |
|
|
: list-size ( list -- u ) \ gforth-internal |
: list-size ( list -- u ) \ gforth-internal |
\ size of the locals frame represented by list |
\ size of the locals frame represented by list |
Line 203 variable locals-dp \ so here's the speci
|
Line 247 variable locals-dp \ so here's the speci
|
\ 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 ; |
|
|
Line 222 variable locals-dp \ so here's the speci
|
Line 266 variable locals-dp \ so here's the speci
|
locals-size @ swap ! |
locals-size @ swap ! |
postpone lp@ postpone c! ; |
postpone lp@ postpone c! ; |
|
|
|
7 cells 32 + constant locals-name-size \ 32-char name + fields + wiggle room |
|
|
|
: create-local1 ( "name" -- a-addr ) |
|
create |
|
immediate restrict |
|
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 ) |
: create-local ( " name" -- a-addr ) |
\ defines the local "name"; the offset of the local shall be |
\ defines the local "name"; the offset of the local shall be |
\ stored in a-addr |
\ stored in a-addr |
create |
locals-name-size allocate throw |
immediate restrict |
dup locals-mem-list prepend-list |
here 0 , ( place for the offset ) ; |
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 |
Line 313 forth definitions
|
Line 390 forth definitions
|
also locals-types |
also locals-types |
|
|
\ these "locals" are used for comparison in TO |
\ these "locals" are used for comparison in TO |
|
|
c: some-clocal 2drop |
c: some-clocal 2drop |
d: some-dlocal 2drop |
d: some-dlocal 2drop |
f: some-flocal 2drop |
f: some-flocal 2drop |
w: some-wlocal 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 |
Line 352 new-locals-map mappedwordlist Constant n
|
Line 430 new-locals-map mappedwordlist Constant n
|
\ 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 |
: { ( -- latestxt wid 0 ) \ gforth open-brace |
: { ( -- latestxt wid 0 ) \ gforth open-brace |
dp old-dpp ! |
|
locals-dp dpp ! |
|
latestxt get-current |
latestxt 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 |
Line 368 locals-types definitions
|
Line 442 locals-types definitions
|
|
|
: } ( latestxt 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 |
Line 498 forth definitions
|
Line 572 forth definitions
|
latest latestxt |
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 ; |
Line 638 forth definitions
|
Line 713 forth definitions
|
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 |
Line 650 forth definitions
|
Line 725 forth definitions
|
>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 |
Line 686 forth definitions
|
Line 761 forth definitions
|
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 |