Commit | Line | Data |
---|---|---|
85d70fb7 JM |
1 | GOTO MAIN |
2 | ||
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' | |
8 | REM $INCLUDE: 'core.in.bas' | |
9 | ||
9e8f5211 JM |
10 | REM $INCLUDE: 'debug.in.bas' |
11 | ||
cc9dbd92 | 12 | REM READ(A$) -> R |
85d70fb7 JM |
13 | MAL_READ: |
14 | GOSUB READ_STR | |
15 | RETURN | |
16 | ||
cc9dbd92 | 17 | REM EVAL_AST(A, E) -> R |
af621e3a | 18 | SUB EVAL_AST |
cc9dbd92 | 19 | REM push A and E on the stack |
bbab5c5d | 20 | X=X+2:X%(X-1)=E:X%(X)=A |
85d70fb7 | 21 | |
cc9dbd92 | 22 | IF ER<>-2 THEN GOTO EVAL_AST_RETURN |
85d70fb7 JM |
23 | |
24 | GOSUB DEREF_A | |
25 | ||
bbab5c5d | 26 | T=Z%(A,0)AND31 |
cc9dbd92 JM |
27 | IF T=5 THEN GOTO EVAL_AST_SYMBOL |
28 | IF T>=6 AND T<=8 THEN GOTO EVAL_AST_SEQ | |
85d70fb7 JM |
29 | |
30 | REM scalar: deref to actual value and inc ref cnt | |
cc9dbd92 | 31 | R=A:GOSUB DEREF_R |
bbab5c5d | 32 | Z%(R,0)=Z%(R,0)+32 |
85d70fb7 JM |
33 | GOTO EVAL_AST_RETURN |
34 | ||
35 | EVAL_AST_SYMBOL: | |
af621e3a JM |
36 | K=A:GOTO ENV_GET |
37 | ENV_GET_RETURN: | |
85d70fb7 JM |
38 | GOTO EVAL_AST_RETURN |
39 | ||
40 | EVAL_AST_SEQ: | |
a742287e JM |
41 | REM allocate the first entry (T already set above) |
42 | L=0:N=0:GOSUB ALLOC | |
85d70fb7 JM |
43 | |
44 | REM make space on the stack | |
cc9dbd92 | 45 | X=X+4 |
85d70fb7 | 46 | REM push type of sequence |
bbab5c5d | 47 | X%(X-3)=T |
85d70fb7 | 48 | REM push sequence index |
bbab5c5d | 49 | X%(X-2)=-1 |
85d70fb7 | 50 | REM push future return value (new sequence) |
bbab5c5d | 51 | X%(X-1)=R |
85d70fb7 | 52 | REM push previous new sequence entry |
bbab5c5d | 53 | X%(X)=R |
85d70fb7 JM |
54 | |
55 | EVAL_AST_SEQ_LOOP: | |
85d70fb7 | 56 | REM update index |
bbab5c5d | 57 | X%(X-2)=X%(X-2)+1 |
85d70fb7 JM |
58 | |
59 | REM check if we are done evaluating the source sequence | |
cc9dbd92 | 60 | IF Z%(A,1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE |
85d70fb7 | 61 | |
01e8850d JM |
62 | REM if we are returning to DO, then skip last element |
63 | IF X%(X-6)=2 AND Z%(Z%(A,1),1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE | |
64 | ||
85d70fb7 | 65 | REM if hashmap, skip eval of even entries (keys) |
c7330b3d | 66 | IF (X%(X-3)=8) AND ((X%(X-2)AND1)=0) THEN GOTO EVAL_AST_DO_REF |
85d70fb7 JM |
67 | GOTO EVAL_AST_DO_EVAL |
68 | ||
69 | EVAL_AST_DO_REF: | |
cc9dbd92 | 70 | R=A+1:GOSUB DEREF_R: REM deref to target of referred entry |
bbab5c5d | 71 | Z%(R,0)=Z%(R,0)+32: REM inc ref cnt of referred value |
85d70fb7 JM |
72 | GOTO EVAL_AST_ADD_VALUE |
73 | ||
74 | EVAL_AST_DO_EVAL: | |
75 | REM call EVAL for each entry | |
af621e3a | 76 | A=A+1:CALL EVAL |
cc9dbd92 | 77 | A=A-1 |
85d70fb7 JM |
78 | GOSUB DEREF_R: REM deref to target of evaluated entry |
79 | ||
80 | EVAL_AST_ADD_VALUE: | |
81 | ||
82 | REM update previous value pointer to evaluated entry | |
bbab5c5d | 83 | Z%(X%(X)+1,1)=R |
85d70fb7 | 84 | |
cc9dbd92 | 85 | IF ER<>-2 THEN GOTO EVAL_AST_SEQ_LOOP_DONE |
85d70fb7 JM |
86 | |
87 | REM allocate the next entry | |
a742287e | 88 | REM same new sequence entry type |
bbab5c5d | 89 | T=X%(X-3):L=0:N=0:GOSUB ALLOC |
85d70fb7 JM |
90 | |
91 | REM update previous sequence entry value to point to new entry | |
bbab5c5d | 92 | Z%(X%(X),1)=R |
85d70fb7 | 93 | REM update previous ptr to current entry |
bbab5c5d | 94 | X%(X)=R |
85d70fb7 JM |
95 | |
96 | REM process the next sequence entry from source list | |
cc9dbd92 | 97 | A=Z%(A,1) |
85d70fb7 JM |
98 | |
99 | GOTO EVAL_AST_SEQ_LOOP | |
100 | EVAL_AST_SEQ_LOOP_DONE: | |
9e8f5211 | 101 | REM if no error, get return value (new seq) |
bbab5c5d | 102 | IF ER=-2 THEN R=X%(X-1) |
9e8f5211 | 103 | REM otherwise, free the return value and return nil |
bbab5c5d | 104 | IF ER<>-2 THEN R=0:AY=X%(X-1):GOSUB RELEASE |
85d70fb7 JM |
105 | |
106 | REM pop previous, return, index and type | |
cc9dbd92 | 107 | X=X-4 |
85d70fb7 JM |
108 | GOTO EVAL_AST_RETURN |
109 | ||
110 | EVAL_AST_RETURN: | |
cc9dbd92 | 111 | REM pop A and E off the stack |
bbab5c5d | 112 | E=X%(X-1):A=X%(X):X=X-2 |
af621e3a | 113 | END SUB |
85d70fb7 | 114 | |
af621e3a JM |
115 | REM EVAL(A, E) -> R |
116 | SUB EVAL | |
cc9dbd92 | 117 | LV=LV+1: REM track basic return stack level |
85d70fb7 | 118 | |
cc9dbd92 | 119 | REM push A and E on the stack |
bbab5c5d | 120 | X=X+2:X%(X-1)=E:X%(X)=A |
85d70fb7 | 121 | |
01e8850d JM |
122 | REM PRINT "EVAL A:"+STR$(A)+",X:"+STR$(X)+",LV:"+STR$(LV)+",FRE:"+STR$(FRE(0)) |
123 | ||
85d70fb7 JM |
124 | EVAL_TCO_RECUR: |
125 | ||
c7330b3d JM |
126 | IF ER<>-2 THEN GOTO EVAL_RETURN |
127 | ||
cc9dbd92 JM |
128 | REM AZ=A:PR=1:GOSUB PR_STR |
129 | REM PRINT "EVAL: "+R$+" [A:"+STR$(A)+", LV:"+STR$(LV)+"]" | |
85d70fb7 JM |
130 | |
131 | GOSUB DEREF_A | |
132 | ||
133 | GOSUB LIST_Q | |
cc9dbd92 | 134 | IF R THEN GOTO APPLY_LIST |
85d70fb7 | 135 | REM ELSE |
af621e3a | 136 | CALL EVAL_AST |
85d70fb7 JM |
137 | GOTO EVAL_RETURN |
138 | ||
139 | APPLY_LIST: | |
140 | GOSUB EMPTY_Q | |
bbab5c5d | 141 | IF R THEN R=A:Z%(R,0)=Z%(R,0)+32:GOTO EVAL_RETURN |
85d70fb7 | 142 | |
bbab5c5d JM |
143 | A0=A+1 |
144 | R=A0:GOSUB DEREF_R:A0=R | |
85d70fb7 JM |
145 | |
146 | REM get symbol in A$ | |
bbab5c5d JM |
147 | IF (Z%(A0,0)AND31)<>5 THEN A$="" |
148 | IF (Z%(A0,0)AND31)=5 THEN A$=S$(Z%(A0,1)) | |
85d70fb7 JM |
149 | |
150 | IF A$="def!" THEN GOTO EVAL_DEF | |
151 | IF A$="let*" THEN GOTO EVAL_LET | |
152 | IF A$="do" THEN GOTO EVAL_DO | |
153 | IF A$="if" THEN GOTO EVAL_IF | |
154 | IF A$="fn*" THEN GOTO EVAL_FN | |
155 | GOTO EVAL_INVOKE | |
156 | ||
157 | EVAL_GET_A3: | |
bbab5c5d JM |
158 | A3=Z%(Z%(Z%(A,1),1),1)+1 |
159 | R=A3:GOSUB DEREF_R:A3=R | |
85d70fb7 | 160 | EVAL_GET_A2: |
bbab5c5d JM |
161 | A2=Z%(Z%(A,1),1)+1 |
162 | R=A2:GOSUB DEREF_R:A2=R | |
85d70fb7 | 163 | EVAL_GET_A1: |
bbab5c5d JM |
164 | A1=Z%(A,1)+1 |
165 | R=A1:GOSUB DEREF_R:A1=R | |
85d70fb7 JM |
166 | RETURN |
167 | ||
168 | EVAL_DEF: | |
169 | REM PRINT "def!" | |
bbab5c5d | 170 | GOSUB EVAL_GET_A2: REM set A1 and A2 |
85d70fb7 | 171 | |
bbab5c5d | 172 | X=X+1:X%(X)=A1: REM push A1 |
af621e3a | 173 | A=A2:CALL EVAL: REM eval a2 |
bbab5c5d | 174 | A1=X%(X):X=X-1: REM pop A1 |
85d70fb7 | 175 | |
cc9dbd92 | 176 | IF ER<>-2 THEN GOTO EVAL_RETURN |
70f29a2b | 177 | |
85d70fb7 | 178 | REM set a1 in env to a2 |
bbab5c5d | 179 | K=A1:V=R:GOSUB ENV_SET |
85d70fb7 JM |
180 | GOTO EVAL_RETURN |
181 | ||
182 | EVAL_LET: | |
183 | REM PRINT "let*" | |
bbab5c5d | 184 | GOSUB EVAL_GET_A2: REM set A1 and A2 |
85d70fb7 | 185 | |
bbab5c5d JM |
186 | X=X+1:X%(X)=A2: REM push/save A2 |
187 | X=X+1:X%(X)=E: REM push env for for later release | |
85d70fb7 JM |
188 | |
189 | REM create new environment with outer as current environment | |
cc9dbd92 JM |
190 | O=E:GOSUB ENV_NEW |
191 | E=R | |
85d70fb7 | 192 | EVAL_LET_LOOP: |
bbab5c5d | 193 | IF Z%(A1,1)=0 THEN GOTO EVAL_LET_LOOP_DONE |
85d70fb7 | 194 | |
bbab5c5d | 195 | X=X+1:X%(X)=A1: REM push A1 |
85d70fb7 | 196 | REM eval current A1 odd element |
af621e3a | 197 | A=Z%(A1,1)+1:CALL EVAL |
bbab5c5d | 198 | A1=X%(X):X=X-1: REM pop A1 |
85d70fb7 | 199 | |
c7330b3d JM |
200 | IF ER<>-2 THEN GOTO EVAL_LET_LOOP_DONE |
201 | ||
bbab5c5d JM |
202 | REM set environment: even A1 key to odd A1 eval'd above |
203 | K=A1+1:V=R:GOSUB ENV_SET | |
cc9dbd92 | 204 | AY=R:GOSUB RELEASE: REM release our use, ENV_SET took ownership |
85d70fb7 | 205 | |
bbab5c5d JM |
206 | REM skip to the next pair of A1 elements |
207 | A1=Z%(Z%(A1,1),1) | |
85d70fb7 | 208 | GOTO EVAL_LET_LOOP |
70f29a2b | 209 | |
85d70fb7 | 210 | EVAL_LET_LOOP_DONE: |
bbab5c5d | 211 | E4=X%(X):X=X-1: REM pop previous env |
70f29a2b JM |
212 | |
213 | REM release previous environment if not the current EVAL env | |
bbab5c5d | 214 | IF E4<>X%(X-2) THEN AY=E4:GOSUB RELEASE |
85d70fb7 | 215 | |
bbab5c5d JM |
216 | A2=X%(X):X=X-1: REM pop A2 |
217 | A=A2:GOTO EVAL_TCO_RECUR: REM TCO loop | |
85d70fb7 JM |
218 | |
219 | EVAL_DO: | |
cc9dbd92 | 220 | A=Z%(A,1): REM rest |
01e8850d | 221 | X=X+1:X%(X)=A: REM push/save A |
85d70fb7 | 222 | |
af621e3a | 223 | CALL EVAL_AST |
85d70fb7 | 224 | |
01e8850d JM |
225 | REM cleanup |
226 | AY=R: REM get eval'd list for release | |
227 | ||
228 | A=X%(X):X=X-1: REM pop/restore original A for LAST | |
229 | GOSUB LAST: REM get last element for return | |
230 | A=R: REM new recur AST | |
231 | ||
232 | REM cleanup | |
233 | GOSUB RELEASE: REM release eval'd list | |
234 | AY=A:GOSUB RELEASE: REM release LAST value (not sure why) | |
235 | ||
236 | GOTO EVAL_TCO_RECUR: REM TCO loop | |
85d70fb7 JM |
237 | |
238 | EVAL_IF: | |
bbab5c5d | 239 | GOSUB EVAL_GET_A1: REM set A1 |
cc9dbd92 | 240 | REM push A |
bbab5c5d | 241 | X=X+1:X%(X)=A |
af621e3a | 242 | A=A1:CALL EVAL |
cc9dbd92 | 243 | REM pop A |
bbab5c5d | 244 | A=X%(X):X=X-1 |
cc9dbd92 | 245 | IF (R=0) OR (R=1) THEN GOTO EVAL_IF_FALSE |
85d70fb7 JM |
246 | |
247 | EVAL_IF_TRUE: | |
cc9dbd92 | 248 | AY=R:GOSUB RELEASE |
bbab5c5d JM |
249 | GOSUB EVAL_GET_A2: REM set A1 and A2 after EVAL |
250 | A=A2:GOTO EVAL_TCO_RECUR: REM TCO loop | |
85d70fb7 | 251 | EVAL_IF_FALSE: |
cc9dbd92 | 252 | AY=R:GOSUB RELEASE |
bbab5c5d | 253 | REM if no false case (A3), return nil |
c7330b3d JM |
254 | B=A:GOSUB COUNT |
255 | IF R<4 THEN R=0:GOTO EVAL_RETURN | |
bbab5c5d JM |
256 | GOSUB EVAL_GET_A3: REM set A1 - A3 after EVAL |
257 | A=A3:GOTO EVAL_TCO_RECUR: REM TCO loop | |
85d70fb7 JM |
258 | |
259 | EVAL_FN: | |
bbab5c5d JM |
260 | GOSUB EVAL_GET_A2: REM set A1 and A2 |
261 | A=A2:P=A1:GOSUB MAL_FUNCTION | |
85d70fb7 JM |
262 | GOTO EVAL_RETURN |
263 | ||
264 | EVAL_INVOKE: | |
af621e3a | 265 | CALL EVAL_AST |
85d70fb7 JM |
266 | |
267 | REM if error, return f/args for release by caller | |
cc9dbd92 | 268 | IF ER<>-2 THEN GOTO EVAL_RETURN |
85d70fb7 JM |
269 | |
270 | REM push f/args for release after call | |
bbab5c5d | 271 | X=X+1:X%(X)=R |
85d70fb7 | 272 | |
cc9dbd92 | 273 | F=R+1 |
85d70fb7 | 274 | |
cc9dbd92 JM |
275 | AR=Z%(R,1): REM rest |
276 | R=F:GOSUB DEREF_R:F=R | |
85d70fb7 | 277 | |
bbab5c5d JM |
278 | REM if metadata, get the actual object |
279 | IF (Z%(F,0)AND31)>=16 THEN F=Z%(F,1) | |
280 | ||
281 | IF (Z%(F,0)AND31)=9 THEN GOTO EVAL_DO_FUNCTION | |
282 | IF (Z%(F,0)AND31)=10 THEN GOTO EVAL_DO_MAL_FUNCTION | |
85d70fb7 JM |
283 | |
284 | REM if error, pop and return f/args for release by caller | |
bbab5c5d | 285 | R=X%(X):X=X-1 |
cc9dbd92 | 286 | ER=-1:ER$="apply of non-function":GOTO EVAL_RETURN |
85d70fb7 JM |
287 | |
288 | EVAL_DO_FUNCTION: | |
01e8850d | 289 | REM regular function |
af621e3a | 290 | IF Z%(F,1)<60 THEN GOSUB DO_FUNCTION:GOTO EVAL_DO_FUNCTION_SKIP |
01e8850d | 291 | REM for recur functions (apply, map, swap!), use GOTO |
af621e3a JM |
292 | IF Z%(F,1)>60 THEN CALL DO_TCO_FUNCTION |
293 | EVAL_DO_FUNCTION_SKIP: | |
85d70fb7 JM |
294 | |
295 | REM pop and release f/args | |
bbab5c5d | 296 | AY=X%(X):X=X-1:GOSUB RELEASE |
85d70fb7 JM |
297 | GOTO EVAL_RETURN |
298 | ||
299 | EVAL_DO_MAL_FUNCTION: | |
bbab5c5d | 300 | E4=E: REM save the current environment for release |
85d70fb7 JM |
301 | |
302 | REM create new environ using env stored with function | |
bbab5c5d | 303 | O=Z%(F+1,1):BI=Z%(F+1,0):EX=AR:GOSUB ENV_NEW_BINDS |
85d70fb7 JM |
304 | |
305 | REM release previous env if it is not the top one on the | |
bbab5c5d | 306 | REM stack (X%(X-2)) because our new env refers to it and |
85d70fb7 | 307 | REM we no longer need to track it (since we are TCO recurring) |
bbab5c5d | 308 | IF E4<>X%(X-2) THEN AY=E4:GOSUB RELEASE |
85d70fb7 JM |
309 | |
310 | REM claim the AST before releasing the list containing it | |
bbab5c5d | 311 | A=Z%(F,1):Z%(A,0)=Z%(A,0)+32 |
9e8f5211 | 312 | REM add AST to pending release queue to free as soon as EVAL |
cc9dbd92 | 313 | REM actually returns (LV+1) |
bbab5c5d | 314 | Y=Y+1:Y%(Y,0)=A:Y%(Y,1)=LV+1 |
85d70fb7 JM |
315 | |
316 | REM pop and release f/args | |
bbab5c5d | 317 | AY=X%(X):X=X-1:GOSUB RELEASE |
85d70fb7 | 318 | |
cc9dbd92 JM |
319 | REM A set above |
320 | E=R:GOTO EVAL_TCO_RECUR: REM TCO loop | |
85d70fb7 JM |
321 | |
322 | EVAL_RETURN: | |
cc9dbd92 JM |
323 | REM AZ=R: PR=1: GOSUB PR_STR |
324 | REM PRINT "EVAL_RETURN R: ["+R$+"] ("+STR$(R)+"), LV:"+STR$(LV)+",ER:"+STR$(ER) | |
9e8f5211 | 325 | |
85d70fb7 | 326 | REM release environment if not the top one on the stack |
bbab5c5d | 327 | IF E<>X%(X-1) THEN AY=E:GOSUB RELEASE |
85d70fb7 | 328 | |
cc9dbd92 | 329 | LV=LV-1: REM track basic return stack level |
9e8f5211 | 330 | |
85d70fb7 JM |
331 | REM release everything we couldn't release earlier |
332 | GOSUB RELEASE_PEND | |
333 | ||
85d70fb7 | 334 | REM trigger GC |
bbab5c5d | 335 | TA=FRE(0) |
85d70fb7 | 336 | |
cc9dbd92 | 337 | REM pop A and E off the stack |
bbab5c5d | 338 | E=X%(X-1):A=X%(X):X=X-2 |
85d70fb7 | 339 | |
af621e3a | 340 | END SUB |
85d70fb7 | 341 | |
cc9dbd92 | 342 | REM PRINT(A) -> R$ |
85d70fb7 | 343 | MAL_PRINT: |
cc9dbd92 | 344 | AZ=A:PR=1:GOSUB PR_STR |
85d70fb7 JM |
345 | RETURN |
346 | ||
cc9dbd92 | 347 | REM RE(A$) -> R |
bbab5c5d | 348 | REM Assume D has repl_env |
85d70fb7 JM |
349 | REM caller must release result |
350 | RE: | |
cc9dbd92 | 351 | R1=0 |
85d70fb7 | 352 | GOSUB MAL_READ |
cc9dbd92 | 353 | R1=R |
0e508fa5 | 354 | IF ER<>-2 THEN GOTO RE_DONE |
85d70fb7 | 355 | |
af621e3a | 356 | A=R:E=D:CALL EVAL |
85d70fb7 | 357 | |
0e508fa5 | 358 | RE_DONE: |
85d70fb7 | 359 | REM Release memory from MAL_READ |
cc9dbd92 | 360 | IF R1<>0 THEN AY=R1:GOSUB RELEASE |
85d70fb7 JM |
361 | RETURN: REM caller must release result of EVAL |
362 | ||
363 | REM REP(A$) -> R$ | |
bbab5c5d | 364 | REM Assume D has repl_env |
af621e3a | 365 | SUB REP |
cc9dbd92 | 366 | R1=0:R2=0 |
85d70fb7 | 367 | GOSUB MAL_READ |
cc9dbd92 JM |
368 | R1=R |
369 | IF ER<>-2 THEN GOTO REP_DONE | |
85d70fb7 | 370 | |
af621e3a | 371 | A=R:E=D:CALL EVAL |
cc9dbd92 JM |
372 | R2=R |
373 | IF ER<>-2 THEN GOTO REP_DONE | |
85d70fb7 | 374 | |
cc9dbd92 | 375 | A=R:GOSUB MAL_PRINT |
85d70fb7 JM |
376 | RT$=R$ |
377 | ||
378 | REP_DONE: | |
379 | REM Release memory from MAL_READ and EVAL | |
cc9dbd92 JM |
380 | IF R2<>0 THEN AY=R2:GOSUB RELEASE |
381 | IF R1<>0 THEN AY=R1:GOSUB RELEASE | |
85d70fb7 | 382 | R$=RT$ |
af621e3a | 383 | END SUB |
85d70fb7 JM |
384 | |
385 | REM MAIN program | |
386 | MAIN: | |
387 | GOSUB INIT_MEMORY | |
388 | ||
cc9dbd92 | 389 | LV=0 |
85d70fb7 JM |
390 | |
391 | REM create repl_env | |
bbab5c5d | 392 | O=-1:GOSUB ENV_NEW:D=R |
85d70fb7 JM |
393 | |
394 | REM core.EXT: defined in Basic | |
bbab5c5d | 395 | E=D:GOSUB INIT_CORE_NS: REM set core functions in repl_env |
85d70fb7 | 396 | |
bbab5c5d | 397 | ZT=ZI: REM top of memory after base repl_env |
85d70fb7 JM |
398 | |
399 | REM core.mal: defined using the language itself | |
60ef223c | 400 | A$="(def! not (fn* (a) (if a false true)))" |
cc9dbd92 | 401 | GOSUB RE:AY=R:GOSUB RELEASE |
85d70fb7 | 402 | |
0e508fa5 | 403 | A$="(def! load-file (fn* (f) (eval (read-file f))))" |
cc9dbd92 | 404 | GOSUB RE:AY=R:GOSUB RELEASE |
85d70fb7 JM |
405 | |
406 | REM load the args file | |
407 | A$="(def! -*ARGS*- (load-file "+CHR$(34)+".args.mal"+CHR$(34)+"))" | |
cc9dbd92 | 408 | GOSUB RE:AY=R:GOSUB RELEASE |
85d70fb7 JM |
409 | |
410 | REM set the argument list | |
60ef223c | 411 | A$="(def! *ARGV* (rest -*ARGS*-))" |
cc9dbd92 | 412 | GOSUB RE:AY=R:GOSUB RELEASE |
85d70fb7 JM |
413 | |
414 | REM get the first argument | |
60ef223c JM |
415 | A$="(first -*ARGS*-)" |
416 | GOSUB RE | |
85d70fb7 JM |
417 | |
418 | REM if there is an argument, then run it as a program | |
cc9dbd92 | 419 | IF R<>0 THEN AY=R:GOSUB RELEASE:GOTO RUN_PROG |
85d70fb7 | 420 | REM no arguments, start REPL loop |
cc9dbd92 | 421 | IF R=0 THEN GOTO REPL_LOOP |
85d70fb7 JM |
422 | |
423 | RUN_PROG: | |
424 | REM run a single mal program and exit | |
60ef223c JM |
425 | A$="(load-file (first -*ARGS*-))" |
426 | GOSUB RE | |
cc9dbd92 | 427 | IF ER<>-2 THEN GOSUB PRINT_ERROR |
01e8850d | 428 | GOTO QUIT |
85d70fb7 JM |
429 | |
430 | REPL_LOOP: | |
60ef223c | 431 | A$="user> ":GOSUB READLINE: REM call input parser |
85d70fb7 JM |
432 | IF EOF=1 THEN GOTO QUIT |
433 | ||
af621e3a | 434 | A$=R$:CALL REP: REM call REP |
85d70fb7 | 435 | |
cc9dbd92 | 436 | IF ER<>-2 THEN GOSUB PRINT_ERROR:GOTO REPL_LOOP |
85d70fb7 JM |
437 | PRINT R$ |
438 | GOTO REPL_LOOP | |
439 | ||
440 | QUIT: | |
4e7d8a1b | 441 | REM GOSUB PR_MEMORY_SUMMARY |
85d70fb7 JM |
442 | END |
443 | ||
444 | PRINT_ERROR: | |
bf8d1f7d | 445 | PRINT "Error: "+ER$ |
cc9dbd92 | 446 | ER=-2:ER$="" |
85d70fb7 JM |
447 | RETURN |
448 |