Merge pull request #75 from SeekingMeaning/0BSD
[pforth] / fth / ansilocs.fth
CommitLineData
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
29anew task-ansilocs.fth
30
31private{
32
33decimal
3416 constant LV_MAX_VARS \ maximum number of local variables
3531 constant LV_MAX_CHARS \ maximum number of letters in name
36
37lv_max_vars lv_max_chars $array LV-NAMES
38variable 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
114if.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
8e9db35f
PB
145: VALUE
146 CREATE ( n <name> )
147 ,
8e9db35f 148 DOES>
146f755d 149 @
8e9db35f
PB
150;
151
152: TO ( val <name> -- )
153 bl word
154 lv.match
155 IF ( -- index )
156 lv.compile.store
157 ELSE
158 find
146f755d 159 0= abort" not found"
8e9db35f
PB
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
146f755d 181 0= abort" not found"
8e9db35f
PB
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
198privatize