3 REM $INCLUDE: 'readline.in.bas'
4 REM $INCLUDE: 'types.in.bas'
5 REM $INCLUDE: 'reader.in.bas'
6 REM $INCLUDE: 'printer.in.bas'
7 REM $INCLUDE: 'env.in.bas'
9 REM $INCLUDE: 'debug.in.bas'
16 REM EVAL_AST(A, E) -> R
20 REM push A and E on the stack
21 X
=X
+2:X
%(X
-1)=E
:X
%(X
)=A
23 IF ER
<>-2 THEN GOTO EVAL_AST_RETURN
28 IF T
=5 THEN GOTO EVAL_AST_SYMBOL
29 IF T
>=6 AND T
<=8 THEN GOTO EVAL_AST_SEQ
31 REM scalar: deref to actual value and inc ref cnt
42 REM allocate the first entry (T already set above)
45 REM make space on the stack
47 REM push type of sequence
49 REM push sequence index
51 REM push future return value (new sequence)
53 REM push previous new sequence entry
60 REM check if we are done evaluating the source sequence
61 IF Z
%(A
,1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
63 REM if hashmap, skip eval of even entries (keys)
64 IF (X
%(X
-3)=8) AND ((X
%(X
-2)AND1
)=0) THEN GOTO EVAL_AST_DO_REF
68 R
=A
+1:GOSUB DEREF_R
: REM deref to target of referred entry
69 Z
%(R
,0)=Z
%(R
,0)+32: REM inc ref cnt of referred value
70 GOTO EVAL_AST_ADD_VALUE
73 REM call EVAL for each entry
76 GOSUB DEREF_R
: REM deref to target of evaluated entry
80 REM update previous value pointer to evaluated entry
83 IF ER
<>-2 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
85 REM allocate the next entry
86 REM same new sequence entry type
87 T
=X
%(X
-3):L
=0:N
=0:GOSUB ALLOC
89 REM update previous sequence entry value to point to new entry
91 REM update previous ptr to current entry
94 REM process the next sequence entry from source list
97 GOTO EVAL_AST_SEQ_LOOP
98 EVAL_AST_SEQ_LOOP_DONE:
99 REM if no error, get return value (new seq)
100 IF ER
=-2 THEN R
=X
%(X
-1)
101 REM otherwise, free the return value and return nil
102 IF ER
<>-2 THEN R
=0:AY
=X
%(X
-1):GOSUB RELEASE
104 REM pop previous, return, index and type
109 REM pop A and E off the stack
110 E
=X
%(X
-1):A
=X
%(X
):X
=X
-2
117 LV
=LV
+1: REM track basic return stack level
119 REM push A and E on the stack
120 X
=X
+2:X
%(X
-1)=E
:X
%(X
)=A
122 IF ER
<>-2 THEN GOTO EVAL_RETURN
124 REM AZ=A:PR=1:GOSUB PR_STR
125 REM PRINT "EVAL: "+R$+" [A:"+STR$(A)+", LV:"+STR$(LV)+"]"
130 IF R
THEN GOTO APPLY_LIST
137 IF R
THEN R
=A
:Z
%(R
,0)=Z
%(R
,0)+32:GOTO EVAL_RETURN
140 R
=A0
:GOSUB DEREF_R
:A0
=R
143 IF (Z
%(A0
,0)AND31
)<>5 THEN A
$=""
144 IF (Z
%(A0
,0)AND31
)=5 THEN A
$=S$(Z%(A0,1))
146 IF A
$="def!" THEN GOTO EVAL_DEF
147 IF A
$="let*" THEN GOTO EVAL_LET
151 A3
=Z
%(Z
%(Z
%(A
,1),1),1)+1
152 R
=A3
:GOSUB DEREF_R
:A3
=R
155 R
=A2
:GOSUB DEREF_R
:A2
=R
158 R
=A1
:GOSUB DEREF_R
:A1
=R
163 GOSUB EVAL_GET_A2
: REM set A1 and A2
165 X
=X
+1:X
%(X
)=A1
: REM push A1
166 A
=A2
:CALL EVAL
: REM eval a2
167 A1
=X
%(X
):X
=X
-1: REM pop A1
169 IF ER
<>-2 THEN GOTO EVAL_RETURN
171 REM set a1 in env to a2
172 K
=A1
:V
=R
:GOSUB ENV_SET
177 GOSUB EVAL_GET_A2
: REM set A1 and A2
179 X
=X
+1:X
%(X
)=A2
: REM push/save A2
180 REM create new environment with outer as current environment
184 IF Z
%(A1
,1)=0 THEN GOTO EVAL_LET_LOOP_DONE
186 X
=X
+1:X
%(X
)=A1
: REM push A1
187 REM eval current A1 odd element
188 A
=Z
%(A1
,1)+1:CALL EVAL
189 A1
=X
%(X
):X
=X
-1: REM pop A1
191 IF ER
<>-2 THEN GOTO EVAL_LET_LOOP_DONE
193 REM set environment: even A1 key to odd A1 eval'd above
194 K
=A1
+1:V
=R
:GOSUB ENV_SET
195 AY
=R
:GOSUB RELEASE
: REM release our use, ENV_SET took ownership
197 REM skip to the next pair of A1 elements
202 A2
=X
%(X
):X
=X
-1: REM pop A2
203 A
=A2
:CALL EVAL
: REM eval A2 using let_env
209 REM if error, return f/args for release by caller
210 IF ER
<>-2 THEN GOTO EVAL_RETURN
214 R
=F
:GOSUB DEREF_R
:F
=R
215 IF (Z
%(F
,0)AND31
)<>9 THEN ER
=-1:ER
$="apply of non
-function":GOTO EVAL_RETURN
221 REM AZ=R: PR=1: GOSUB PR_STR
222 REM PRINT "EVAL_RETURN R
: ["+R$+"] ("+STR
$(R)+"), LV
:"+STR$(LV)+",ER:"+STR$(ER)
224 REM release environment if not the top one on the stack
225 IF E<>X%(X-1) THEN AY=E:GOSUB RELEASE
227 LV=LV-1: REM track basic return stack level
233 REM pop A and E off the stack
234 E=X%(X-1):A=X%(X):X=X-2
238 REM DO_FUNCTION(F, AR)
245 REM Get the function number
248 REM Get argument values
249 R=AR+1:GOSUB DEREF_R:AA=Z%(R,1)
250 R=Z%(AR,1)+1:GOSUB DEREF_R:AB=Z%(R,1)
252 REM Switch on the function number
253 IF FF=1 THEN GOTO DO_ADD
254 IF FF=2 THEN GOTO DO_SUB
255 IF FF=3 THEN GOTO DO_MULT
256 IF FF=4 THEN GOTO DO_DIV
257 ER=-1:ER$="unknown function"+STR
$(FF):RETURN
260 T
=2:L
=AA
+AB
:GOSUB ALLOC
261 GOTO DO_FUNCTION_DONE
263 T
=2:L
=AA
-AB
:GOSUB ALLOC
264 GOTO DO_FUNCTION_DONE
266 T
=2:L
=AA
*AB
:GOSUB ALLOC
267 GOTO DO_FUNCTION_DONE
269 T
=2:L
=AA
/AB
:GOSUB ALLOC
270 GOTO DO_FUNCTION_DONE
277 AZ
=A
:PR
=1:GOSUB PR_STR
281 REM Assume D has repl_env
286 IF ER
<>-2 THEN GOTO REP_DONE
290 IF ER
<>-2 THEN GOTO REP_DONE
296 REM Release memory from MAL_READ and EVAL
297 IF R2
<>0 THEN AY
=R2
:GOSUB RELEASE
298 IF R1
<>0 THEN AY
=R1
:GOSUB RELEASE
309 O
=-1:GOSUB ENV_NEW
:D
=R
313 A
=1:GOSUB NATIVE_FUNCTION
314 K
$="+":V=R:GOSUB ENV_SET_S
317 A
=2:GOSUB NATIVE_FUNCTION
318 K
$="-":V=R:GOSUB ENV_SET_S
321 A
=3:GOSUB NATIVE_FUNCTION
322 K
$="*":V=R:GOSUB ENV_SET_S
325 A
=4:GOSUB NATIVE_FUNCTION
326 K
$="/":V=R:GOSUB ENV_SET_S
328 ZT
=ZI
: REM top of memory after base repl_env
331 A
$="user> ":GOSUB READLINE: REM call input parser
332 IF EOF=1 THEN GOTO QUIT
334 A$=R$:CALL REP: REM call REP
336 IF ER<>-2 THEN GOSUB PRINT_ERROR:GOTO REPL_LOOP
341 REM P1=ZT: P2=-1: GOSUB PR_MEMORY
342 GOSUB PR_MEMORY_SUMMARY