Copyright Bill Muench All rights reserved.
Permission is granted for non-commercial use, provided this notice is included.
Contact Bill Muench concerning commercial use.
CR .( Locals test )
CR ( Copyright Bill Muench All rights reserved. )
( Bill Muench \ OntoLogic )
( \ Santa Cruz CA 95065 )
( ANS local variables )
( 961206 bee w32f and i21 add name parsing )
( NOT tested on eForth )
( ???need to code runtime words )
( 950503 bee 68332 )
( 920305 bee start with Z80 )
( ???CATCH/THROW )
DECIMAL
( ============================================================== )
( compatibility )
( Win32Forth specific )
' CAPS-FIND IS FIND ( basics only )
' NOOP IS STACK-CHECK ( disable )
EMPTY
10 CONSTANT [W32F?] IMMEDIATE
: DELIMIT ( 'name< >' -- a u ) BL WORD COUNT ;
[W32F?] [IF]
: LSTACKFIX ( n -- -n ) CELLS NEGATE ; ( w32f return stack builds down )
( ABS>REL is defined )
( LP is defined as the Local Pointer )
[ELSE] ( bForth version === must be re-defined for other systems === )
: ABS>REL ( a -- a ) ; IMMEDIATE ( bForth )
: LSTACKFIX ( n -- n ) 1- CELLS ; ( bForth return stack builds up )
\ 40 USER LP ( -- a ) ( locals pointer ) ( bForth ) \ ??? multitasking
[THEN]
( ============================================================== )
( locals runtime, all these need to be in code )
( bForth version === must be re-defined for other systems === )
: L@ ( -- x ) R@ ABS>REL @ LP @ + @ R> CELL+ >R ;
: L! ( -- x ) R@ ABS>REL @ LP @ + ! R> CELL+ >R ;
: L{ ( i*x -- ) ( R: -- a i*x ) ( build locals frame )
R> LP @ >R RP@ LP ! DUP ABS>REL @
BEGIN ?DUP WHILE ROT >R 1- REPEAT CELL+ >R ;
: }L ( -- ) ( R: a i*x -- ) ( remove locals frame )
R> LP @ RP! R> LP ! >R ;
( ============================================================== )
( locals compiler internals )
8 CONSTANT #LOCALS
CREATE LV$ ( -- a ) \ ???smaller
31 1 + CHARS #LOCALS * ALLOT ( room for counted strings )
: LV? ( a u -- index | 0 ) ( find requested locals index )
LV$ 1 >R ( init index )
BEGIN COUNT ?DUP
WHILE 2OVER 2OVER COMPARE 0= ( *** case sensative *** )
IF 2DROP 2DROP R> EXIT THEN + R> 1+ >R
REPEAT R> 2DROP 2DROP 0 ; ( not a local )
VARIABLE LCHAR
VARIABLE LOCALS?
: LVREV ( n i -- i ) ( reverse args for { } form )
NIP LCHAR @ [CHAR] } = IF LOCALS? @ 1+ SWAP - THEN LSTACKFIX ;
: LVFIND ( a -- a 0 | xt -1 ) ( patch for compiler FIND )
DUP COUNT LV? ?DUP ( try locals first )
IF LVREV POSTPONE L@ -1 EXIT ( pass index to be 'compiled' ) \ ???problem
THEN CAPS-FIND ;
: SETLVFIND ( -- ) ['] LVFIND IS FIND ;
: (LOCAL) ( a u -- ) ( save counted string )
LOCALS? @ OVER 1+ LOCALS? +! 2DUP C! CHAR+ SWAP MOVE ;
: XLOCALS| ( c '<spaces>i*name<spaces"c">' -- )
>R LOCALS? @ DUP ABORT" LOCALS| only once" LV$ LOCALS? !
BEGIN DELIMIT OVER C@ R@ - OVER 1- OR
WHILE (LOCAL) 1+ #LOCALS OVER U< ABORT" too many locals"
REPEAT 2DROP 0 DUP (LOCAL) ( add null string )
R> LCHAR ! DUP LOCALS? ! ?DUP IF POSTPONE L{ , THEN ;
: ?LOCALS ( -- ) LOCALS? @ IF POSTPONE }L THEN ;
: : ( 'name' -- ) 0 DUP LOCALS? ! LV$ ! : ;
: EXIT ( -- ) ?LOCALS POSTPONE EXIT ; IMMEDIATE
: ; ( -- ) ?LOCALS POSTPONE ; ; IMMEDIATE
SETLVFIND
( ============================================================== )
( locals user interface )
: LOCALS| ( '<spaces>i*name<spaces|spaces>' -- ) [CHAR] | XLOCALS| ; IMMEDIATE
: { ( '<spaces>i*name<spaces}>' -- ) [CHAR] } XLOCALS| ; IMMEDIATE
: TO ( 'local' -- )
>IN @ DELIMIT LV? ?DUP ( try locals first )
IF LVREV POSTPONE L! , EXIT
THEN >IN ! POSTPONE TO ( chain for VALUEs )
; IMMEDIATE
\S ==============================================================
( tests )
: J1 ( n n -- ) LOCALS| GREEN RED | RED . GREEN . ;
: J2 ( n n -- ) LOCALS| RED GREEN | RED . GREEN . ;
: J3 ( n n -- ) LOCALS| | . . ;
: J4 ( n n n -- ) LOCALS| RED GREEN SPOT | RED . GREEN . SPOT . ;
: J5 ( -- ) LOCALS| A B C D E F G H | ;
: J6 ( -- ) LOCALS| A B C D E F G H | A . B . C . D . E . F . G . H . ;
: J7 ( -- ) LOCALS| A B C D E F G H J | ; ( FAILS, to many locals )
( ============================================================== )
: K1 ( -- ) LOCALS| A | A . ;
: K2 ( -- ) LOCALS| A B | A . B . ;
: K3 ( -- ) LOCALS| A B C | A . B . C . ;
: K4 ( -- ) LOCALS| A B C D | A . B . C . D . ;
: K5 ( -- ) LOCALS| A B C D E | A . B . C . D . E . ;
: K6 ( -- ) LOCALS| A B C D E F | A . B . C . D . E . F . ;
: K7 ( -- ) LOCALS| A B C D E F G | A . B . C . D . E . F . G . ;
: K8 ( -- ) LOCALS| A B C D E F G H | A . B . C . D . E . F . G . H . ;
: KK ( -- 1 2 3 4 5 6 7 8 9 ) 1 2 3 4 5 6 7 8 9 ;
: K9 ( -- ) { A B C D E F G H } A . B . C . D . E . F . G . H . ;
( ============================================================== )
: QQ ( -- ) ( display the local names )
CR LV$ BEGIN COUNT ?DUP WHILE 2DUP TYPE + 2 SPACES REPEAT DROP ;
: Q1 ( -- ) LOCALS| A B PEACH GREEN C D | ; QQ
: Q2 ( -- ) LOCALS| PEACH GREEN C D SPOT | ; QQ
( ============================================================== )
0 VALUE V0
: T1 ( -- )
." should display 60 50 10" CR
10 20 30 LOCALS| RED GREEN SPOT | 0 IF RED DROP EXIT THEN ( test EXIT )
RED GREEN + DUP TO GREEN SPOT + TO RED RED . GREEN . SPOT TO V0 V0 . ;
( ============================================================== )
VARIABLE X 0 X !
: T2 ( -- 444 )
444 555 666 LOCALS| RED GREEN | CR RED . RP@ . X @ THROW ( restore LP )
;
: T3 ( -- 111 )
111 222 333
LOCALS| RED GREEN | CR RED . RP@ . LP @ >R [ ' T2 ] LITERAL CATCH ( save LP )
IF R> LP ! CR ." error " RP@ .
ELSE R> DROP CR ." ok red " RP@ .
THEN RED . ;
( ============================================================== )
: T6 ( n n n -- n ) \ ??? ANS considered a violation, but works
LOCALS| RED GREEN | RED GREEN + >R RED GREEN - R> . . . ;
: T7 ( -- ) 1 2 7 T6 ;
: T8 ( u GREEN RED -- ) ( DO-LOOP works )
LOCALS| RED GREEN | 0 ?DO CR RED . GREEN . LOOP ;
( ============================================================== )
: T9 ( n n n -- n ) ( this is a VIOLATION, and it FAILS )
>R LOCALS| RED GREEN | RED GREEN + RED GREEN - R> . . . ;
( ============================================================== )