Updated README with better build info
[debian/pforth] / fth / ansilocs.fth
1 \ @(#) ansilocs.fth 98/01/26 1.3
2 \ local variable support words
3 \ These support the ANSI standard (LOCAL) and TO words.
4 \
5 \ They are built from the following low level primitives written in 'C':
6 \    (local@) ( i+1 -- n , fetch from ith local variable )
7 \    (local!) ( n i+1 -- , store to ith local variable )
8 \    (local.entry) ( num -- , allocate stack frame for num local variables )
9 \    (local.exit)  ( -- , free local variable stack frame )
10 \    local-compiler ( -- addr , variable containing CFA of locals compiler )
11 \
12 \ Author: Phil Burk
13 \ Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
14 \
15 \ Permission to use, copy, modify, and/or distribute this
16 \ software for any purpose with or without fee is hereby granted.
17 \
18 \ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
19 \ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
20 \ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
21 \ THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
22 \ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
23 \ FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
24 \ CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
25 \ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 \
27 \ 10/27/99 Fixed  : foo { -- } 55 ; was entering local frame but not exiting.
28
29 anew task-ansilocs.fth
30
31 private{
32
33 decimal
34 16 constant LV_MAX_VARS    \ maximum number of local variables
35 31 constant LV_MAX_CHARS   \ maximum number of letters in name
36
37 lv_max_vars lv_max_chars $array LV-NAMES
38 variable LV-#NAMES   \ number of names currently defined
39
40 \ Search name table for match
41 : LV.MATCH ( $string -- index true | $string false )
42     0 swap
43     lv-#names @ 0
44     ?DO  i lv-names
45         over $=
46         IF  2drop true i LEAVE
47         THEN
48     LOOP swap
49 ;
50
51 : LV.COMPILE.FETCH  ( index -- )
52     1+  \ adjust for optimised (local@), LocalsPtr points above vars
53     CASE
54     1 OF compile (1_local@) ENDOF
55     2 OF compile (2_local@) ENDOF
56     3 OF compile (3_local@) ENDOF
57     4 OF compile (4_local@) ENDOF
58     5 OF compile (5_local@) ENDOF
59     6 OF compile (6_local@) ENDOF
60     7 OF compile (7_local@) ENDOF
61     8 OF compile (8_local@) ENDOF
62     dup [compile] literal compile (local@)
63     ENDCASE
64 ;
65
66 : LV.COMPILE.STORE  ( index -- )
67     1+  \ adjust for optimised (local!), LocalsPtr points above vars
68     CASE
69     1 OF compile (1_local!) ENDOF
70     2 OF compile (2_local!) ENDOF
71     3 OF compile (3_local!) ENDOF
72     4 OF compile (4_local!) ENDOF
73     5 OF compile (5_local!) ENDOF
74     6 OF compile (6_local!) ENDOF
75     7 OF compile (7_local!) ENDOF
76     8 OF compile (8_local!) ENDOF
77     dup [compile] literal compile (local!)
78     ENDCASE
79 ;
80
81 : LV.COMPILE.LOCAL  ( $name -- handled? , check for matching locals name )
82 \ ." LV.COMPILER.LOCAL name = " dup count type cr
83     lv.match
84     IF ( index )
85         lv.compile.fetch
86         true
87     ELSE
88         drop false
89     THEN
90 ;
91
92 : LV.CLEANUP ( -- , restore stack frame on exit from colon def )
93     lv-#names @
94     IF
95         compile (local.exit)
96     THEN
97 ;
98 : LV.FINISH ( -- , restore stack frame on exit from colon def )
99     lv.cleanup
100     lv-#names off
101     local-compiler off
102 ;
103
104 : LV.SETUP ( -- )
105     0 lv-#names !
106 ;
107
108 : LV.TERM
109     ." Locals turned off" cr
110     lv-#names off
111     local-compiler off
112 ;
113
114 if.forgotten lv.term
115
116 }private
117
118 : (LOCAL)  ( adr len -- , ANSI local primitive )
119     dup
120     IF
121         lv-#names @ lv_max_vars >= abort" Too many local variables!"
122         lv-#names @  lv-names place
123 \ Warn programmer if local variable matches an existing dictionary name.
124         lv-#names @  lv-names find nip
125         IF
126             ." (LOCAL) - Note: "
127             lv-#names @  lv-names count type
128             ."  redefined as a local variable in "
129             latest id. cr
130         THEN
131         1 lv-#names +!
132     ELSE
133 \ Last local. Finish building local stack frame.
134         2drop
135         lv-#names @ dup 0=  \ fixed 10/27/99, Thanks to John Providenza
136         IF
137             drop ." (LOCAL) - Warning: no locals defined!" cr
138         ELSE
139             [compile] literal   compile (local.entry)
140             ['] lv.compile.local local-compiler !
141         THEN
142     THEN
143 ;
144
145 : VALUE
146     CREATE ( n <name> )
147         ,
148     DOES>
149         @
150 ;
151
152 : TO  ( val <name> -- )
153     bl word
154     lv.match
155     IF  ( -- index )
156         lv.compile.store
157     ELSE
158         find
159         0= abort" not found"
160         >body  \ point to data
161         state @
162         IF  \ compiling  ( -- pfa )
163             [compile] aliteral
164             compile !
165         ELSE \ executing  ( -- val pfa )
166             !
167         THEN
168     THEN
169 ; immediate
170
171 : ->  ( -- )  [compile] to  ; immediate
172
173 : +->  ( val <name> -- )
174     bl word
175     lv.match
176     IF  ( -- index )
177         1+  \ adjust for optimised (local!), LocalsPtr points above vars
178         [compile] literal compile (local+!)
179     ELSE
180         find
181         0= abort" not found"
182         >body  \ point to data
183         state @
184         IF  \ compiling  ( -- pfa )
185             [compile] aliteral
186             compile +!
187         ELSE \ executing  ( -- val pfa )
188             +!
189         THEN
190     THEN
191 ; immediate
192
193 : :      lv.setup   : ;
194 : ;      lv.finish  [compile] ;      ; immediate
195 : exit   lv.cleanup  compile exit   ; immediate
196 : does>  lv.finish  [compile] does>  ; immediate
197
198 privatize