5393eff1945c527706715e4ccc5d569f1f026c8b
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) AND 1)=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 REM AZ=A:PR=1:GOSUB PR_STR
123 REM PRINT "EVAL: "+R$+" [A:"+STR$(A)+", LV:"+STR$(LV)+"]"
128 IF R
THEN GOTO APPLY_LIST
135 IF R
THEN R
=A
:Z
%(R
,0)=Z
%(R
,0)+32:GOTO EVAL_RETURN
138 R
=A0
:GOSUB DEREF_R
:A0
=R
141 IF (Z
%(A0
,0)AND31
)<>5 THEN A
$=""
142 IF (Z
%(A0
,0)AND31
)=5 THEN A
$=S$(Z%(A0,1))
144 IF A
$="def!" THEN GOTO EVAL_DEF
145 IF A
$="let*" THEN GOTO EVAL_LET
149 A3
=Z
%(Z
%(Z
%(A
,1),1),1)+1
150 R
=A3
:GOSUB DEREF_R
:A3
=R
153 R
=A2
:GOSUB DEREF_R
:A2
=R
156 R
=A1
:GOSUB DEREF_R
:A1
=R
161 GOSUB EVAL_GET_A2
: REM set A1 and A2
163 X
=X
+1:X
%(X
)=A1
: REM push A1
164 A
=A2
:CALL EVAL
: REM eval a2
165 A1
=X
%(X
):X
=X
-1: REM pop A1
167 IF ER
<>-2 THEN GOTO EVAL_RETURN
169 REM set a1 in env to a2
170 K
=A1
:V
=R
:GOSUB ENV_SET
175 GOSUB EVAL_GET_A2
: REM set A1 and A2
177 X
=X
+1:X
%(X
)=A2
: REM push/save A2
178 REM create new environment with outer as current environment
182 IF Z
%(A1
,1)=0 THEN GOTO EVAL_LET_LOOP_DONE
184 X
=X
+1:X
%(X
)=A1
: REM push A1
185 REM eval current A1 odd element
186 A
=Z
%(A1
,1)+1:CALL EVAL
187 A1
=X
%(X
):X
=X
-1: REM pop A1
189 REM set environment: even A1 key to odd A1 eval'd above
190 K
=A1
+1:V
=R
:GOSUB ENV_SET
191 AY
=R
:GOSUB RELEASE
: REM release our use, ENV_SET took ownership
193 REM skip to the next pair of A1 elements
198 A2
=X
%(X
):X
=X
-1: REM pop A2
199 A
=A2
:CALL EVAL
: REM eval A2 using let_env
205 REM if error, return f/args for release by caller
206 IF ER
<>-2 THEN GOTO EVAL_RETURN
210 R
=F
:GOSUB DEREF_R
:F
=R
211 IF (Z
%(F
,0)AND31
)<>9 THEN ER
=-1:ER
$="apply of non
-function":GOTO EVAL_RETURN
217 REM AZ=R: PR=1: GOSUB PR_STR
218 REM PRINT "EVAL_RETURN R
: ["+R$+"] ("+STR
$(R)+"), LV
:"+STR$(LV)+",ER:"+STR$(ER)
220 REM release environment if not the top one on the stack
221 IF E<>X%(X-1) THEN AY=E:GOSUB RELEASE
223 LV=LV-1: REM track basic return stack level
229 REM pop A and E off the stack
230 E=X%(X-1):A=X%(X):X=X-2
234 REM DO_FUNCTION(F, AR)
241 REM Get the function number
244 REM Get argument values
245 R=AR+1:GOSUB DEREF_R:AA=Z%(R,1)
246 R=Z%(AR,1)+1:GOSUB DEREF_R:AB=Z%(R,1)
248 REM Switch on the function number
249 IF FF=1 THEN GOTO DO_ADD
250 IF FF=2 THEN GOTO DO_SUB
251 IF FF=3 THEN GOTO DO_MULT
252 IF FF=4 THEN GOTO DO_DIV
253 ER=-1:ER$="unknown function"+STR
$(FF):RETURN
256 T
=2:L
=AA
+AB
:GOSUB ALLOC
257 GOTO DO_FUNCTION_DONE
259 T
=2:L
=AA
-AB
:GOSUB ALLOC
260 GOTO DO_FUNCTION_DONE
262 T
=2:L
=AA
*AB
:GOSUB ALLOC
263 GOTO DO_FUNCTION_DONE
265 T
=2:L
=AA
/AB
:GOSUB ALLOC
266 GOTO DO_FUNCTION_DONE
273 AZ
=A
:PR
=1:GOSUB PR_STR
277 REM Assume D has repl_env
282 IF ER
<>-2 THEN GOTO REP_DONE
286 IF ER
<>-2 THEN GOTO REP_DONE
292 REM Release memory from MAL_READ and EVAL
293 IF R2
<>0 THEN AY
=R2
:GOSUB RELEASE
294 IF R1
<>0 THEN AY
=R1
:GOSUB RELEASE
305 O
=-1:GOSUB ENV_NEW
:D
=R
309 A
=1:GOSUB NATIVE_FUNCTION
310 K
$="+":V=R:GOSUB ENV_SET_S
313 A
=2:GOSUB NATIVE_FUNCTION
314 K
$="-":V=R:GOSUB ENV_SET_S
317 A
=3:GOSUB NATIVE_FUNCTION
318 K
$="*":V=R:GOSUB ENV_SET_S
321 A
=4:GOSUB NATIVE_FUNCTION
322 K
$="/":V=R:GOSUB ENV_SET_S
324 ZT
=ZI
: REM top of memory after base repl_env
327 A
$="user> ":GOSUB READLINE: REM call input parser
328 IF EOF=1 THEN GOTO QUIT
330 A$=R$:CALL REP: REM call REP
332 IF ER<>-2 THEN GOSUB PRINT_ERROR:GOTO REPL_LOOP
337 REM P1=ZT: P2=-1: GOSUB PR_MEMORY
338 GOSUB PR_MEMORY_SUMMARY