2 REM DO_FUNCTION(F%, AR%)
4 REM Get the function number
7 REM Get argument values
8 R
%=AR
%+1:GOSUB DEREF_R
:AA
%=R
%
9 R
%=Z
%(AR
%,1)+1:GOSUB DEREF_R
:AB
%=R
%
11 REM Switch on the function number
12 IF FF
%>=61 THEN ER
%=1:ER
$="unknown function"+STR$(FF%):RETURN
19 ON FF% GOTO DO_EQUAL_Q
20 REM IF FF%=1 THEN DO_EQUAL_Q
23 ON FF%-10 GOTO DO_PR_STR,DO_STR,DO_PRN,DO_PRINTLN,DO_READLINE,DO_READ_STRING,DO_SLURP
24 REM IF FF%=11 THEN DO_PR_STR
25 REM IF FF%=12 THEN DO_STR
26 REM IF FF%=13 THEN DO_PRN
27 REM IF FF%=14 THEN DO_PRINTLN
28 REM IF FF%=15 THEN DO_READLINE
29 REM IF FF%=16 THEN DO_READ_STRING
30 REM IF FF%=17 THEN DO_SLURP
33 ON FF%-17 GOTO DO_LT,DO_LTE,DO_GT,DO_GTE,DO_ADD,DO_SUB,DO_MULT,DO_DIV,DO_TIME_MS
34 REM IF FF%=18 THEN DO_LT
35 REM IF FF%=19 THEN DO_LTE
36 REM IF FF%=20 THEN DO_GT
37 REM IF FF%=21 THEN DO_GTE
38 REM IF FF%=22 THEN DO_ADD
39 REM IF FF%=23 THEN DO_SUB
40 REM IF FF%=24 THEN DO_MULT
41 REM IF FF%=25 THEN DO_DIV
42 REM IF FF%=26 THEN DO_TIME_MS
45 ON FF%-26 GOTO DO_LIST,DO_LIST_Q
46 REM IF FF%=27 THEN DO_LIST
47 REM IF FF%=28 THEN DO_LIST_Q
50 ON FF%-39 GOTO DO_CONS,DO_CONCAT,DO_NTH,DO_FIRST,DO_REST,DO_EMPTY_Q,DO_COUNT
51 REM IF FF%=40 THEN DO_CONS
52 REM IF FF%=41 THEN DO_CONCAT
53 REM IF FF%=42 THEN DO_NTH
54 REM IF FF%=43 THEN DO_FIRST
55 REM IF FF%=44 THEN DO_REST
56 REM IF FF%=45 THEN DO_EMPTY_Q
57 REM IF FF%=46 THEN DO_COUNT
60 ON FF%-52 GOTO DO_ATOM,DO_ATOM_Q,DO_DEREF,DO_RESET_BANG,DO_SWAP_BANG,DO_PR_MEMORY,DO_PR_MEMORY_SUMMARY,DO_EVAL
61 REM IF FF%=53 THEN DO_ATOM
62 REM IF FF%=54 THEN DO_ATOM_Q
63 REM IF FF%=55 THEN DO_DEREF
64 REM IF FF%=56 THEN DO_RESET_BANG
65 REM IF FF%=57 THEN DO_SWAP_BANG
67 REM IF FF%=58 THEN DO_PR_MEMORY
68 REM IF FF%=59 THEN DO_PR_MEMORY_SUMMARY
69 REM IF FF%=60 THEN DO_EVAL
72 A%=AA%:B%=AB%:GOSUB EQUAL_Q
77 AZ%=AR%:PR%=1:SE$=" ":GOSUB PR_STR_SEQ
78 AS$=R$:T%=4+16:GOSUB STRING
81 AZ
%=AR
%:PR
%=0:SE
$="":GOSUB PR_STR_SEQ
82 AS$=R$:T%=4+16:GOSUB STRING
85 AZ
%=AR
%:PR
%=1:SE
$=" ":GOSUB PR_STR_SEQ
90 AZ%=AR%:PR%=0:SE$=" ":GOSUB PR_STR_SEQ
102 REM OPEN 1,8,2,ZS$(Z%(AA%,1))+",SEQ,R"
103 REM OPEN 1,8,2,ZS$(Z%(AA%,1))
104 OPEN
1,8,0,ZS
$(Z%(AA%,1))
108 IF ASC(A
$)=10 THEN R
$=R$+CHR$(13)
109 IF (ASC(A
$)<>10) AND (A
$<>"") THEN R
$=R$+A$
110 IF (ST
AND 64) THEN GOTO DO_SLURP_DONE
111 IF (ST
AND 255) THEN ER
%=-1:ER
%="File read error "+STR
$(ST):RETURN
115 AS$=R$:T%=4+16:GOSUB STRING
120 IF Z
%(AA
%,1)<Z
%(AB
%,1) THEN R
%=2
124 IF Z
%(AA
%,1)<=Z
%(AB
%,1) THEN R
%=2
128 IF Z
%(AA
%,1)>Z
%(AB
%,1) THEN R
%=2
132 IF Z
%(AA
%,1)>=Z
%(AB
%,1) THEN R
%=2
138 Z
%(R
%,1)=Z
%(AA
%,1)+Z
%(AB
%,1)
143 Z
%(R
%,1)=Z
%(AA
%,1)-Z
%(AB
%,1)
148 Z
%(R
%,1)=Z
%(AA
%,1)*Z
%(AB
%,1)
153 Z
%(R
%,1)=Z
%(AA
%,1)/Z
%(AB
%,1)
165 R
%=R
%+1: REM map to mal false/true
169 A
%=AA
%:B
%=AB
%:GOSUB CONS
172 REM if empty arguments, return empty list
173 IF Z
%(AR
%,1)=0 THEN R
%=3:Z
%(R
%,0)=Z
%(R
%,0)+16:RETURN
176 IF Z
%(Z
%(AR
%,1),1)<>0 THEN GOTO DO_CONCAT_MULT
177 REM if single argument and it's a list, return it
178 IF (Z
%(AA
%,0)AND15
)=6 THEN R
%=AA
%:Z
%(R
%,0)=Z
%(R
%,0)+16:RETURN
179 REM otherwise, copy first element to turn it into a list
180 B
%=AA
%+1:GOSUB DEREF_B
: REM value to copy
182 Z
%(R
%,0)=6+16:Z
%(R
%,1)=Z
%(AA
%,1)
183 Z
%(R
%+1,0)=14:Z
%(R
%+1,1)=B
%
184 REM inc ref count of trailing list part and of copied value
185 Z
%(Z
%(AA
%,1),0)=Z
%(Z
%(AA
%,1),0)+16
189 REM multiple arguments
191 CZ
%=ZL
%: REM save current stack position
192 REM push arguments onto the stack
194 R
%=AR
%+1:GOSUB DEREF_R
195 ZL
%=ZL
%+1:ZZ
%(ZL
%)=R
%: REM push sequence
197 IF Z
%(AR
%,1)<>0 THEN GOTO DO_CONCAT_STACK
199 REM pop last argument as our seq to prepend to
200 AB
%=ZZ
%(ZL
%):ZL
%=ZL
%-1
201 REM last arg/seq is not copied so we need to inc ref to it
202 Z
%(AB
%,0)=Z
%(AB
%,0)+16
204 IF ZL
%=CZ
% THEN R
%=AB
%:RETURN
205 AA
%=ZZ
%(ZL
%):ZL
%=ZL
%-1: REM pop off next seq to prepend
206 IF Z
%(AA
%,1)=0 THEN GOTO DO_CONCAT_LOOP
: REM skip empty seqs
207 A
%=AA
%:B
%=0:C
%=-1:GOSUB SLICE
209 REM release the terminator of new list (we skip over it)
210 AY
%=Z
%(R6
%,1):GOSUB RELEASE
211 REM attach new list element before terminator (last actual
212 REM element to the next sequence
220 IF R
%<=B
% THEN R
%=0:ER
%=1:ER
$="nth: index out of range
":RETURN
222 IF B%=0 THEN GOTO DO_NTH_DONE
231 IF Z%(AA%,1)=0 THEN R%=0
232 IF Z%(AA%,1)<>0 THEN R%=AA%+1:GOSUB DEREF_R
233 IF R%<>0 THEN Z%(R%,0)=Z%(R%,0)+16
236 IF Z%(AA%,1)=0 THEN R%=AA%
237 IF Z%(AA%,1)<>0 THEN R%=Z%(AA%,1)
242 IF Z%(AA%,1)=0 THEN R%=2
245 A%=AA%:GOSUB COUNT:R4%=R%
253 Z%(AA%,0)=Z%(AA%,0)+16: REM inc ref cnt of contained value
259 IF (Z%(AA%,0)AND15)=12 THEN R%=2
262 R%=Z%(AA%,1):GOSUB DEREF_R
267 REM release current value
268 AY%=Z%(AA%,1):GOSUB RELEASE
269 REM inc ref by 2 for atom ownership and since we are returning it
277 REM add atom to front of the args list
278 A%=Z%(AA%,1):B%=Z%(Z%(AR%,1),1):GOSUB CONS
281 REM push args for release after
282 ZL%=ZL%+1:ZZ%(ZL%)=AR%
285 ZL%=ZL%+1:ZZ%(ZL%)=AA%
290 AA%=ZZ%(ZL%):ZL%=ZL%-1
292 REM pop and release args
293 AY%=ZZ%(ZL%):ZL%=ZL%-1:GOSUB RELEASE
295 REM use reset to update the value
296 AB%=R%:GOSUB DO_RESET_BANG
298 REM but decrease ref cnt of return by 1 (not sure why)
304 P1%=ZT%:P2%=-1:GOSUB PR_MEMORY
306 DO_PR_MEMORY_SUMMARY:
307 GOSUB PR_MEMORY_SUMMARY
311 A%=AA%:E%=RE%:GOSUB EVAL
314 INIT_CORE_SET_FUNCTION:
315 GOSUB NATIVE_FUNCTION
316 V%=R%:GOSUB ENV_SET_S
321 REM create the environment mapping
322 REM must match DO_FUNCTION mappings
324 K$="=":A%=1:GOSUB INIT_CORE_SET_FUNCTION
326 K$="pr-str":A%=11:GOSUB INIT_CORE_SET_FUNCTION
327 K$="str":A%=12:GOSUB INIT_CORE_SET_FUNCTION
328 K$="prn":A%=13:GOSUB INIT_CORE_SET_FUNCTION
329 K$="println":A%=14:GOSUB INIT_CORE_SET_FUNCTION
330 K$="readline":A%=15:GOSUB INIT_CORE_SET_FUNCTION
331 K$="read-string":A%=16:GOSUB INIT_CORE_SET_FUNCTION
332 K$="slurp":A%=17:GOSUB INIT_CORE_SET_FUNCTION
334 K$="<":A%=18:GOSUB INIT_CORE_SET_FUNCTION
335 K$="<=":A%=19:GOSUB INIT_CORE_SET_FUNCTION
336 K$=">":A%=20:GOSUB INIT_CORE_SET_FUNCTION
337 K$=">=":A%=21:GOSUB INIT_CORE_SET_FUNCTION
338 K$="+":A%=22:GOSUB INIT_CORE_SET_FUNCTION
339 K$="-":A%=23:GOSUB INIT_CORE_SET_FUNCTION
340 K$="*":A%=24:GOSUB INIT_CORE_SET_FUNCTION
341 K$="/":A%=25:GOSUB INIT_CORE_SET_FUNCTION
342 K$="time-ms":A%=26:GOSUB INIT_CORE_SET_FUNCTION
344 K$="list":A%=27:GOSUB INIT_CORE_SET_FUNCTION
345 K$="list?":A%=28:GOSUB INIT_CORE_SET_FUNCTION
347 K$="cons":A%=40:GOSUB INIT_CORE_SET_FUNCTION
348 K$="concat":A%=41:GOSUB INIT_CORE_SET_FUNCTION
349 K$="nth":A%=42:GOSUB INIT_CORE_SET_FUNCTION
350 K$="first":A%=43:GOSUB INIT_CORE_SET_FUNCTION
351 K$="rest":A%=44:GOSUB INIT_CORE_SET_FUNCTION
352 K$="empty?":A%=45:GOSUB INIT_CORE_SET_FUNCTION
353 K$="count":A%=46:GOSUB INIT_CORE_SET_FUNCTION
355 K$="atom":A%=53:GOSUB INIT_CORE_SET_FUNCTION
356 K$="atom?":A%=54:GOSUB INIT_CORE_SET_FUNCTION
357 K$="deref":A%=55:GOSUB INIT_CORE_SET_FUNCTION
358 K$="reset!":A%=56:GOSUB INIT_CORE_SET_FUNCTION
359 K$="swap!":A%=57:GOSUB INIT_CORE_SET_FUNCTION
361 K$="pr-memory":A%=58:GOSUB INIT_CORE_SET_FUNCTION
362 K$="pr-memory-summary":A%=59:GOSUB INIT_CORE_SET_FUNCTION
363 K$="eval":A%=60:GOSUB INIT_CORE_SET_FUNCTION