On Saturday, February 16, 2013 11:40:38 AM UTC-7, Brad Eckert wrote:
> Hi All,
>
>
>
> I think locals should have scope over a group of words, not a single word. The last word in the scope can be assumed to set up the locals frame and then take it down at the end. Does anyone have a syntax to do this?
>
I whittled it down to SCOPE: and SCOPE;, providing some extra modularity in the process. The following code is a sample implementation followed by a usage example.
\ Localized scoping mechanism
\ With "local" variables implemented as variables in a temporary
\ frame on a frame stack. The benefits of this are:
\ 1. Information hiding
\ 2. Reduced RAM waste via reclamation of temporary storage
\ 3. Simpler reentrancy
0 [if]
SCOPE: ( <name> -- )
Begins a private wordlist.
SCOPE; ( -- )
Restores the search order and current wordlist.
When compiling, <name> compiles code to manage a stack frame for
local variables. Otherwise, <name> restores the scope to its
previous state and search order, to facilitate debugging.
[then]
\ frame stack run time
VARIABLE FPTR
1024 BUFFER: FRAMESTACK
: DO-REFRAME ( n -- ) FPTR +! ;
: FPTR[N] ( n -- a ) FPTR @ SWAP - ;
: /FPTR ( -- ) FRAMESTACK FPTR ! ; /FPTR
\ frame stack compile time
: RE-FRAME ( offset -- )
ALIGNED POSTPONE LITERAL POSTPONE DO-REFRAME
;
VARIABLE THIS-SCOPE \ -> current scope
VARIABLE SCOPED \ flag: frame needs to be handled
\ Allocate space in the frame for data. Note that VARIABLEs are not
\ automatically initialized to zero, as classic VARIABLEs often are.
: _LOCALBUF ( <name> n -- ) \ create item and allocate space
THIS-SCOPE @ DUP 0= ABORT" Scope does not exist"
@ SWAP
THIS-SCOPE @ +!
CREATE , DOES> @
STATE @ IF
POSTPONE LITERAL POSTPONE FPTR[N]
ELSE FPTR[N]
THEN
;
: _UNFRAME ( -- ) \ remove the locals frame
SCOPED @ IF
THIS-SCOPE @ ?DUP IF \ is there a frame?
@ NEGATE RE-FRAME \ compile code to take it down.
THEN THEN
;
: UN_SCOPE ( -- ) \ after ; some cleanup...
SCOPED @ IF PREVIOUS PREVIOUS 0 SCOPED ! THEN
;
WORDLIST CONSTANT SCOPELEX \ special lexicon for scoping
SCOPELEX +ORDER DEFINITIONS
: VARIABLE ( <name> -- ) 1 CELLS _LOCALBUF ;
: BUFFER: ( <name> n -- ) _LOCALBUF ;
: EXIT ( cs -- ) _UNFRAME POSTPONE EXIT ; IMMEDIATE
: ; ( cs -- ) _UNFRAME POSTPONE ; UN_SCOPE ; IMMEDIATE
PREVIOUS DEFINITIONS
: SCOPE: ( <name> -- ) \ create a new scope
WORDLIST SCOPELEX +ORDER DUP +ORDER
CREATE IMMEDIATE
HERE THIS-SCOPE ! 0 , , \ offset wid
DOES>
DUP THIS-SCOPE ! SCOPELEX +ORDER
DUP CELL+ @ +ORDER
STATE @ IF
@ RE-FRAME TRUE SCOPED !
ELSE DROP THEN
;
: SCOPE; ( -- )
PREVIOUS PREVIOUS DEFINITIONS
0 THIS-SCOPE !
;
\ test drive
\ -------------------------------------------------------------------
SCOPE: ROOTS
VARIABLE A
VARIABLE B
VARIABLE C
: DETERMINANT ( -- n ) \ b^2 - 4ac
B @ DUP * A @ C @ * 4 * - ;
: ROOT ( n1 -- n2 ) 2/ ; \ okay, we fake the square root
SCOPE;
: ROOT1 ( a b c -- n )
ROOTS C ! B ! A !
B @ NEGATE DETERMINANT ROOT + A @ 2/ ;
ROOTS \ let's add another variable for this version
VARIABLE D
SCOPE;
: ROOT2 ( a b c -- n )
ROOTS C ! B ! A ! 8 D !
B @ NEGATE DETERMINANT ROOT - A @ 2/ D @ + ;
\ As a bonus, WORDS only lists what's in ROOTS