--- gforth/glocals.fs 2004/12/31 13:23:57 1.55 +++ gforth/glocals.fs 2012/01/16 22:17:32 1.64 @@ -1,12 +1,12 @@ \ A powerful locals implementation -\ Copyright (C) 1995,1996,1997,1998,2000,2003,2004 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. \ Gforth is free software; you can redistribute it and/or \ 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. \ This program is distributed in the hope that it will be useful, @@ -15,8 +15,7 @@ \ GNU General Public License for more details. \ You should have received a copy of the GNU General Public License -\ along with this program; if not, write to the Free Software -\ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. +\ along with this program. If not, see http://www.gnu.org/licenses/. \ More documentation can be found in the manual and in @@ -89,6 +88,10 @@ require search.fs require float.fs require extend.fs \ for case +: save-mem-dict ( addr1 u -- addr2 u ) + here swap dup allot ( addr1 addr2 u ) + 2dup 2>r move 2r> ; + : compile-@local ( n -- ) \ gforth compile-fetch-local case 0 of postpone @local0 endof @@ -133,11 +136,22 @@ vocabulary locals \ this contains the lo ' locals >body wordlist-id ' locals-list >body ! slowvoc ! -create locals-buffer 1000 allot \ !! limited and unsafe - \ here the names of the local variables are stored - \ we would have problems storing them at the normal dp +variable locals-mem-list \ linked list of all locals name memory in +0 locals-mem-list ! \ the current (outer-level) definition -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 ) \ cell-align size and generate the corresponding code for aligning lp @@ -203,7 +217,7 @@ variable locals-dp \ so here's the speci \ warn if list is not a sublist of locals-list locals-list @ sub-list? 0= if \ !! 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 then ; @@ -222,12 +236,45 @@ variable locals-dp \ so here's the speci locals-size @ swap ! 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 ) \ defines the local "name"; the offset of the local shall be \ stored in a-addr - create - immediate restrict - here 0 , ( place for the offset ) ; + 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 ) \ converts the offset from the frame start to an offset from lp and @@ -313,11 +360,12 @@ 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. \ we exploit a feature of our dictionary: every wordlist @@ -352,12 +400,8 @@ new-locals-map mappedwordlist Constant n \ slowvoc ! \ new-locals-map ' new-locals >body wordlist-map A! \ !! use special access words -variable old-dpp - \ and now, finally, the user interface words : { ( -- latestxt wid 0 ) \ gforth open-brace - dp old-dpp ! - locals-dp dpp ! latestxt get-current get-order new-locals-wl swap 1+ set-order also locals definitions locals-types @@ -368,7 +412,7 @@ locals-types definitions : } ( latestxt wid 0 a-addr1 xt1 ... -- ) \ gforth close-brace \ ends locals definitions - ] old-dpp @ dpp ! + ] begin dup while @@ -498,7 +542,8 @@ forth definitions latest latestxt clear-leave-stack 0 locals-size ! - locals-buffer locals-dp ! + locals-mem-list @ free-list + 0 locals-mem-list ! 0 locals-list ! dead-code off defstart ; @@ -638,7 +683,7 @@ forth definitions 2drop endif ; -: >definer ( xt -- definer ) +: >definer ( xt -- definer ) \ gforth \G @var{Definer} is a unique identifier for the way the @var{xt} \G was defined. Words defined with different @code{does>}-codes \G have different definers. The definer can be used for @@ -650,7 +695,7 @@ forth definitions >code-address then ; -: definer! ( definer xt -- ) +: definer! ( definer xt -- ) \ gforth \G The word represented by @var{xt} changes its behaviour to the \G behaviour associated with @var{definer}. over 1 and if @@ -686,7 +731,7 @@ forth definitions endcase ; 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 '{' \ implementation is compat/anslocals.fs BEGIN