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'
14 REM EVAL_AST(A%, E%) -> R%
18 REM push A% and E% on the stack
19 ZL
%=ZL
%+2: ZZ
%(ZL
%-1)=E
%: ZZ
%(ZL
%)=A
%
21 IF ER
%<>0 THEN GOTO EVAL_AST_RETURN
23 REM AZ%=A%: GOSUB PR_STR
24 REM PRINT "EVAL_AST: " + R$ + "(" + STR$(A%) + ")"
25 REM PRINT "EVAL_AST level: " + STR$(LV%)
30 IF T
%=5 THEN EVAL_AST_SYMBOL
31 IF T
%=6 THEN EVAL_AST_SEQ
32 IF T
%=7 THEN EVAL_AST_SEQ
33 IF T
%=8 THEN EVAL_AST_SEQ
35 REM scalar: deref to actual value and inc ref cnt
45 REM allocate the first entry
48 REM make space on the stack
50 REM push type of sequence
52 REM push sequence index
54 REM push future return value (new sequence)
56 REM push previous new sequence entry
60 REM set new sequence entry type (with 1 ref cnt)
61 Z
%(R
%,0)=ZZ
%(ZL
%-3)+16
63 REM create value ptr placeholder
68 ZZ
%(ZL
%-2)=ZZ
%(ZL
%-2)+1
70 REM check if we are done evaluating the source sequence
71 IF Z
%(A
%,1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
73 REM if hashmap, skip eval of even entries (keys)
74 IF (ZZ
%(ZL
%-3)=8) AND ((ZZ
%(ZL
%-2) AND 1)=0) THEN GOTO EVAL_AST_DO_REF
78 R
%=A
%+1: GOSUB DEREF_R
: REM deref to target of referred entry
79 Z
%(R
%,0)=Z
%(R
%,0)+16: REM inc ref cnt of referred value
80 GOTO EVAL_AST_ADD_VALUE
83 REM call EVAL for each entry
86 GOSUB DEREF_R
: REM deref to target of evaluated entry
90 REM update previous value pointer to evaluated entry
93 IF ER
%<>0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
95 REM allocate the next entry
98 REM update previous sequence entry value to point to new entry
100 REM update previous ptr to current entry
103 REM process the next sequence entry from source list
106 GOTO EVAL_AST_SEQ_LOOP
107 EVAL_AST_SEQ_LOOP_DONE:
108 REM if no error, get return value (new seq)
109 IF ER
%=0 THEN R
%=ZZ
%(ZL
%-1)
110 REM otherwise, free the return value and return nil
111 IF ER
%<>0 THEN R
%=0: AY
%=ZZ
%(ZL
%-1): GOSUB RELEASE
113 REM pop previous, return, index and type
118 REM pop A% and E% off the stack
119 E
%=ZZ
%(ZL
%-1): A
%=ZZ
%(ZL
%): ZL
%=ZL
%-2
124 REM EVAL(A%, E%)) -> R%
126 LV
%=LV
%+1: REM track basic return stack level
128 REM push A% and E% on the stack
129 ZL
%=ZL
%+2: ZZ
%(ZL
%-1)=E
%: ZZ
%(ZL
%)=A
%
131 REM AZ%=A%: GOSUB PR_STR
132 REM PRINT "EVAL: " + R$ + "(" + STR$(A%) + "), LV%:"+STR$(LV%)
137 IF R
% THEN GOTO APPLY_LIST
144 IF R
% THEN R
%=A
%: Z
%(R
%,0)=Z
%(R
%,0)+16: GOTO EVAL_RETURN
147 R
%=A0
%: GOSUB DEREF_R
: A0
%=R
%
150 IF (Z
%(A0
%,0)AND15
)<>5 THEN A
$=""
151 IF (Z
%(A0
%,0)AND15
)=5 THEN A
$=ZS$(Z%(A0%,1))
153 IF A
$="def!" THEN GOTO EVAL_DEF
154 IF A
$="let*" THEN GOTO EVAL_LET
158 A3
% = Z
%(Z
%(Z
%(A
%,1),1),1)+1
159 R
%=A3
%: GOSUB DEREF_R
: A3
%=R
%
161 A2
% = Z
%(Z
%(A
%,1),1)+1
162 R
%=A2
%: GOSUB DEREF_R
: A2
%=R
%
165 R
%=A1
%: GOSUB DEREF_R
: A1
%=R
%
170 GOSUB EVAL_GET_A2
: REM set a1% and a2%
172 ZL
%=ZL
%+1: ZZ
%(ZL
%)=A1
%: REM push A1%
173 A
%=A2
%: GOSUB EVAL
: REM eval a2
174 A1
%=ZZ
%(ZL
%): ZL
%=ZL
%-1: REM pop A1%
176 REM set a1 in env to a2
177 K
%=A1
%: V
%=R
%: GOSUB ENV_SET
182 GOSUB EVAL_GET_A2
: REM set a1% and a2%
183 REM create new environment with outer as current environment
184 EO
%=E
%: GOSUB ENV_NEW
187 IF Z
%(A1
%,1)=0 THEN GOTO EVAL_LET_LOOP_DONE
190 ZL
%=ZL
%+1: ZZ
%(ZL
%)=A1
%
191 REM eval current A1 odd element
192 A
%=Z
%(A1
%,1)+1: GOSUB EVAL
194 A1
%=ZZ
%(ZL
%): ZL
%=ZL
%-1
196 REM set environment: even A1% key to odd A1% eval'd above
197 K
%=A1
%+1: V
%=R
%: GOSUB ENV_SET
198 AY
%=R
%: GOSUB RELEASE
: REM release our use, ENV_SET took ownership
200 REM skip to the next pair of A1% elements
204 A
%=A2
%: GOSUB EVAL
: REM eval a2 using let_env
210 REM if error, return f/args for release by caller
211 IF ER
%<>0 THEN GOTO EVAL_RETURN
214 AR
%=Z
%(R
%,1): REM rest
215 R
%=F
%: GOSUB DEREF_R
: F
%=R
%
216 IF (Z
%(F
%,0)AND15
)<>9 THEN ER
%=1: ER
$="apply of non
-function": GOTO EVAL_RETURN
218 AY%=R3%: GOSUB RELEASE
222 REM release environment if not the top one on the stack
223 IF E%<>ZZ%(ZL%-1) THEN AY%=E%: GOSUB RELEASE
229 REM pop A% and E% off the stack
230 E%=ZZ%(ZL%-1): A%=ZZ%(ZL%): ZL%=ZL%-2
232 LV%=LV%-1: REM track basic return stack level
236 REM DO_FUNCTION(F%, AR%)
240 AZ%=AR%: GOSUB PR_STR
243 REM Get the function number
246 REM Get argument values
247 R%=AR%+1: GOSUB DEREF_R: AA%=Z%(R%,1)
248 R%=Z%(AR%,1)+1: GOSUB DEREF_R: AB%=Z%(R%,1)
250 REM Allocate the return value
253 REM Switch on the function number
256 IF FF%=3 THEN DO_MULT
258 ER%=1: ER$="unknown function" + STR
$(FF%): RETURN
263 GOTO DO_FUNCTION_DONE
267 GOTO DO_FUNCTION_DONE
271 GOTO DO_FUNCTION_DONE
275 GOTO DO_FUNCTION_DONE
282 AZ
%=A
%: PR
%=1: GOSUB PR_STR
286 REM Assume RE% has repl_env
291 IF ER
%<>0 THEN GOTO REP_DONE
293 A
%=R
%: E
%=RE
%: GOSUB EVAL
295 IF ER
%<>0 THEN GOTO REP_DONE
297 A
%=R
%: GOSUB MAL_PRINT
301 REM Release memory from MAL_READ and EVAL
302 IF R2
%<>0 THEN AY
%=R2
%: GOSUB RELEASE
303 IF R1
%<>0 THEN AY
%=R1
%: GOSUB RELEASE
314 EO
%=-1: GOSUB ENV_NEW
319 A
%=1: GOSUB NATIVE_FUNCTION
320 K
$="+": V
%=R
%: GOSUB ENV_SET_S
323 A
%=2: GOSUB NATIVE_FUNCTION
324 K
$="-": V
%=R
%: GOSUB ENV_SET_S
327 A
%=3: GOSUB NATIVE_FUNCTION
328 K
$="*": V
%=R
%: GOSUB ENV_SET_S
331 A
%=4: GOSUB NATIVE_FUNCTION
332 K
$="/": V
%=R
%: GOSUB ENV_SET_S
334 ZT
%=ZI
%: REM top of memory after base repl_env
338 GOSUB READLINE: REM /* call input parser */
339 IF EOF=1 THEN GOTO QUIT
341 A$=R$: GOSUB REP: REM call REP
343 IF ER%<>0 THEN GOSUB PRINT_ERROR: GOTO REPL_LOOP
348 REM P1%=ZT%: P2%=-1: GOSUB PR_MEMORY
349 GOSUB PR_MEMORY_SUMMARY
353 PRINT "Error: " + ER$