Commit | Line | Data |
---|---|---|
8e9db35f PB |
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 | |
1a088514 | 13 | \ Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom |
8e9db35f | 14 | \ |
1f99f95d S |
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. | |
8e9db35f PB |
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 | ||
146 | : VALUE | |
147 | CREATE ( n <name> ) | |
148 | , | |
149 | immediate | |
150 | DOES> | |
151 | state @ | |
152 | IF | |
153 | [compile] aliteral | |
154 | compile @ | |
155 | ELSE | |
156 | @ | |
157 | THEN | |
158 | ; | |
159 | ||
160 | : TO ( val <name> -- ) | |
161 | bl word | |
162 | lv.match | |
163 | IF ( -- index ) | |
164 | lv.compile.store | |
165 | ELSE | |
166 | find | |
167 | 1 = 0= abort" TO or -> before non-local or non-value" | |
168 | >body \ point to data | |
169 | state @ | |
170 | IF \ compiling ( -- pfa ) | |
171 | [compile] aliteral | |
172 | compile ! | |
173 | ELSE \ executing ( -- val pfa ) | |
174 | ! | |
175 | THEN | |
176 | THEN | |
177 | ; immediate | |
178 | ||
179 | : -> ( -- ) [compile] to ; immediate | |
180 | ||
181 | : +-> ( val <name> -- ) | |
182 | bl word | |
183 | lv.match | |
184 | IF ( -- index ) | |
185 | 1+ \ adjust for optimised (local!), LocalsPtr points above vars | |
186 | [compile] literal compile (local+!) | |
187 | ELSE | |
188 | find | |
189 | 1 = 0= abort" +-> before non-local or non-value" | |
190 | >body \ point to data | |
191 | state @ | |
192 | IF \ compiling ( -- pfa ) | |
193 | [compile] aliteral | |
194 | compile +! | |
195 | ELSE \ executing ( -- val pfa ) | |
196 | +! | |
197 | THEN | |
198 | THEN | |
199 | ; immediate | |
200 | ||
201 | : : lv.setup : ; | |
202 | : ; lv.finish [compile] ; ; immediate | |
203 | : exit lv.cleanup compile exit ; immediate | |
204 | : does> lv.finish [compile] does> ; immediate | |
205 | ||
206 | privatize |