1 REM APPLY should really be in types.in.bas but it is here because it
2 REM has return labels into DO_TCO_FUNCTION so it will cause syntax
3 REM errors for steps1-3 if it is in types.in.bas because there are
8 REM - call using GOTO and with return label/address on the stack
10 REM if metadata, get the actual object
11 IF (Z
%(F
,0)AND31
)>=16 THEN F
=Z
%(F
,1)
13 IF (Z
%(F
,0)AND31
)=9 THEN GOTO APPLY_FUNCTION
14 IF (Z
%(F
,0)AND31
)=10 THEN GOTO APPLY_MAL_FUNCTION
15 IF (Z
%(F
,0)AND31
)=11 THEN GOTO APPLY_MAL_FUNCTION
19 IF Z
%(F
,1)<60 THEN GOSUB DO_FUNCTION
:GOTO DO_TCO_FUNCTION_RETURN_APPLY
20 REM for recur functions (apply, map, swap!), use GOTO
21 IF Z
%(F
,1)>60 THEN X
=X
+1:X
%(X
)=1:GOTO DO_TCO_FUNCTION
22 DO_TCO_FUNCTION_RETURN_APPLY:
26 X
=X
+1:X
%(X
)=E
: REM save the current environment
28 REM create new environ using env and params stored in the
29 REM function and bind the params to the apply arguments
30 O
=Z
%(F
+1,1):BI
=Z
%(F
+1,0):EX
=AR
:GOSUB ENV_NEW_BINDS
32 A
=Z
%(F
,1):E
=R
:GOSUB EVAL
34 AY
=E
:GOSUB RELEASE
: REM release the new environment
36 E
=X
%(X
):X
=X
-1: REM pop/restore the saved environment
39 REM pop APPLY return label/address
41 ON RN
GOTO APPLY_RETURN_1
,APPLY_RETURN_2
,APPLY_RETURN_MAP
,APPLY_RETURN_SWAP
,APPLY_RETURN_MACROEXPAND
44 REM DO_TCO_FUNCTION(F, AR)
45 REM - similar to DO_FUNCTION but non-GOSUB version for potentially
46 REM recursive function (apply, map, swap!)
50 REM Get argument values
51 R
=AR
+1:GOSUB DEREF_R
:AA
=R
52 R
=Z
%(AR
,1)+1:GOSUB DEREF_R
:AB
=R
54 ON FF
-60 GOTO DO_APPLY
,DO_MAP
,DO_SWAP_BANG
62 REM no intermediate args, but not a list, so convert it first
63 IF R4
<=1 AND (Z
%(A
,0)AND31
)<>6 THEN T
=6:GOSUB FORCE_SEQ_TYPE
:GOTO DO_APPLY_2
64 REM no intermediate args, just call APPLY directly
65 IF R4
<=1 THEN GOTO DO_APPLY_1
67 REM prepend intermediate args to final args element
68 A
=AR
:B
=0:C
=R4
-1:GOSUB SLICE
69 REM release the terminator of new list (we skip over it)
70 AY
=Z
%(R6
,1):GOSUB RELEASE
71 REM attach end of slice to final args element
73 Z
%(Z
%(A
+1,1),0)=Z
%(Z
%(A
+1,1),0)+32
78 X
=X
+1:X
%(X
)=1: REM push APPLY return label/address
80 REM APPLY return label/address popped by APPLY
83 GOTO DO_TCO_FUNCTION_RETURN
86 X
=X
+1:X
%(X
)=R
: REM push/save new args for release
88 X
=X
+1:X
%(X
)=2: REM push APPLY return label/address
90 REM APPLY return label/address popped by APPLY
93 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
: REM pop/release new args
94 GOTO DO_TCO_FUNCTION_RETURN
99 REM first result list element
100 T
=6:L
=0:N
=0:GOSUB ALLOC
102 REM push future return val, prior entry, F and AB
103 X
=X
+4:X
%(X
-3)=R
:X
%(X
-2)=0:X
%(X
-1)=F
:X
%(X
)=AB
106 REM set previous to current if not the first element
107 IF X
%(X
-2)<>0 THEN Z
%(X
%(X
-2),1)=R
108 REM update previous reference to current
111 IF Z
%(AB
,1)=0 THEN GOTO DO_MAP_DONE
113 REM create argument list for apply call
115 REM inc ref cnt of referred argument
116 T
=6:L
=3:N
=Z
%(AB
+1,1):GOSUB ALLOC
118 REM push argument list
121 X
=X
+1:X
%(X
)=3: REM push APPLY return label/address
123 REM APPLY return label/address popped by APPLY
126 REM pop apply args are release them
127 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
129 REM set the result value
135 REM update AB to next source element
139 REM allocate next element
140 T
=6:L
=0:N
=0:GOSUB ALLOC
147 REM pop everything off stack
149 GOTO DO_TCO_FUNCTION_RETURN
155 REM add atom to front of the args list
156 T
=6:L
=Z
%(Z
%(AR
,1),1):N
=Z
%(AA
,1):GOSUB ALLOC
: REM cons
159 REM push args for release after
165 X
=X
+1:X
%(X
)=4: REM push APPLY return label/address
167 REM APPLY return label/address popped by APPLY
173 REM pop and release args
174 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
176 REM use reset to update the value
177 AB
=R
:GOSUB DO_RESET_BANG
179 REM but decrease ref cnt of return by 1 (not sure why)
182 GOTO DO_TCO_FUNCTION_RETURN
184 DO_TCO_FUNCTION_RETURN:
185 REM pop EVAL AST return label/address
187 ON RN
GOTO DO_TCO_FUNCTION_RETURN_APPLY
,DO_TCO_FUNCTION_RETURN_EVAL
190 REM DO_FUNCTION(F, AR)
192 REM Get the function number
195 REM Get argument values
196 R
=AR
+1:GOSUB DEREF_R
:AA
=R
197 R
=Z
%(AR
,1)+1:GOSUB DEREF_R
:AB
=R
199 REM Switch on the function number
200 IF FF
>59 THEN ER
=-1:ER
$="unknown function"+STR$(FF):RETURN
201 ON FF/10+1 GOTO DO_1_9,DO_10_19,DO_20_29,DO_30_39,DO_40_49,DO_50_56
204 ON FF GOTO DO_EQUAL_Q,DO_THROW,DO_NIL_Q,DO_TRUE_Q,DO_FALSE_Q,DO_STRING_Q,DO_SYMBOL,DO_SYMBOL_Q,DO_KEYWORD
206 ON FF-9 GOTO DO_KEYWORD_Q,DO_PR_STR,DO_STR,DO_PRN,DO_PRINTLN,DO_READ_STRING,DO_READLINE,DO_SLURP,DO_LT,DO_LTE
208 ON FF-19 GOTO DO_GT,DO_GTE,DO_ADD,DO_SUB,DO_MULT,DO_DIV,DO_TIME_MS,DO_LIST,DO_LIST_Q,DO_VECTOR
210 ON FF-29 GOTO DO_VECTOR_Q,DO_HASH_MAP,DO_MAP_Q,DO_ASSOC,DO_THROW,DO_GET,DO_CONTAINS,DO_KEYS,DO_VALS,DO_SEQUENTIAL_Q
212 ON FF-39 GOTO DO_CONS,DO_CONCAT,DO_NTH,DO_FIRST,DO_REST,DO_EMPTY_Q,DO_COUNT,DO_THROW,DO_THROW,DO_WITH_META
214 ON FF-49 GOTO DO_META,DO_ATOM,DO_ATOM_Q,DO_DEREF,DO_RESET_BANG,DO_EVAL,DO_READ_FILE
217 A=AA:B=AB:GOSUB EQUAL_Q
239 IF (Z%(AA,0)AND31)<>4 THEN RETURN
240 IF MID$(S$(Z%(AA,1)),1,1)=CHR$(127) THEN RETURN
244 T=5:L=Z%(AA,1):GOSUB ALLOC
248 IF (Z%(AA,0)AND31)=5 THEN R=2
253 IF MID$(AS$,1,1)<>CHR$(127) THEN AS$=CHR$(127)+AS$
259 IF (Z%(AA,0)AND31)<>4 THEN RETURN
260 IF MID$(S$(Z%(AA,1)),1,1)<>CHR$(127) THEN RETURN
265 AZ=AR:PR=1:SE$=" ":GOSUB PR_STR_SEQ
266 AS$=R$:T=4:GOSUB STRING
269 AZ
=AR
:PR
=0:SE
$="":GOSUB PR_STR_SEQ
270 AS$=R$:T=4:GOSUB STRING
273 AZ
=AR
:PR
=1:SE
$=" ":GOSUB PR_STR_SEQ
278 AZ=AR:PR=0:SE$=" ":GOSUB PR_STR_SEQ
287 A
$=S$(Z%(AA,1)):GOSUB READLINE
288 IF EOF
=1 THEN EOF
=0:R
=0:RETURN
289 AS$=R$:T=4:GOSUB STRING
293 REM OPEN 1,8,2,S$(Z%(AA,1))+",SEQ,R"
294 REM OPEN 1,8,2,S$(Z%(AA,1))
295 OPEN
1,8,0,S
$(Z%(AA,1))
299 IF ASC(A
$)=10 THEN R
$=R$+CHR$(13)
300 IF (ASC(A
$)<>10) AND (A
$<>"") THEN R
$=R$+A$
301 IF (ST
AND 64) THEN GOTO DO_SLURP_DONE
302 IF (ST
AND 255) THEN ER
=-1:ER
$="File read
error "+STR$(ST):RETURN
306 AS$=R$:T=4:GOSUB STRING
311 IF Z%(AA,1)<Z%(AB,1) THEN R=2
315 IF Z%(AA,1)<=Z%(AB,1) THEN R=2
319 IF Z%(AA,1)>Z%(AB,1) THEN R=2
323 IF Z%(AA,1)>=Z%(AB,1) THEN R=2
327 T=2:L=Z%(AA,1)+Z%(AB,1):GOSUB ALLOC
330 T=2:L=Z%(AA,1)-Z%(AB,1):GOSUB ALLOC
333 T=2:L=Z%(AA,1)*Z%(AB,1):GOSUB ALLOC
336 T=2:L=Z%(AA,1)/Z%(AB,1):GOSUB ALLOC
339 T=2:L=INT((TI-BT)*16.667):GOSUB ALLOC
348 R=R+1: REM map to mal false/true
351 A=AR:T=7:GOSUB FORCE_SEQ_TYPE
355 IF (Z%(AA,0)AND31)=7 THEN R=2
358 A=AR:T=8:GOSUB FORCE_SEQ_TYPE
362 IF (Z%(AA,0)AND31)=8 THEN R=2
368 R=AR+1:GOSUB DEREF_R:K=R
369 R=Z%(AR,1)+1:GOSUB DEREF_R:V=R
373 IF AR=0 OR Z%(AR,1)=0 THEN RETURN
376 IF AA=0 THEN R=0:RETURN
377 H=AA:K=AB:GOSUB HASHMAP_GET
382 H=AA:K=AB:GOSUB HASHMAP_CONTAINS
390 REM first result list element
391 T=6:L=0:N=0:GOSUB ALLOC:T2=R
394 IF AA=0 OR Z%(AA,1)=0 THEN R=T2:RETURN
398 REM inc ref cnt of referred argument
402 T1=R: REM save previous
403 REM allocate next element
404 T=6:L=0:N=0:GOSUB ALLOC
405 REM point previous element to this one
408 IF Z%(Z%(AA,1),1)=0 THEN R=T2:RETURN
412 GOTO DO_KEYS_VALS_LOOP
416 IF (Z%(AA,0)AND31)=6 OR (Z%(AA,0)AND31)=7 THEN R=2
419 T=6:L=AB:N=AA:GOSUB ALLOC
422 REM if empty arguments, return empty list
423 IF Z%(AR,1)=0 THEN R=3:Z%(R,0)=Z%(R,0)+32:RETURN
426 IF Z%(Z%(AR,1),1)<>0 THEN GOTO DO_CONCAT_MULT
427 REM force to list type
428 A=AA:T=6:GOSUB FORCE_SEQ_TYPE
431 REM multiple arguments
433 CZ=X: REM save current stack position
434 REM push arguments onto the stack
437 X=X+1:X%(X)=R: REM push sequence
439 IF Z%(AR,1)<>0 THEN GOTO DO_CONCAT_STACK
441 REM pop last argument as our seq to prepend to
443 REM last arg/seq is not copied so we need to inc ref to it
446 IF X=CZ THEN R=AB:RETURN
447 AA=X%(X):X=X-1: REM pop off next seq to prepend
448 IF Z%(AA,1)=0 THEN GOTO DO_CONCAT_LOOP: REM skip empty seqs
449 A=AA:B=0:C=-1:GOSUB SLICE
451 REM release the terminator of new list (we skip over it)
452 AY=Z%(R6,1):GOSUB RELEASE
453 REM attach new list element before terminator (last actual
454 REM element to the next sequence
462 IF R<=B THEN R=0:ER=-1:ER$="nth: index out of range":RETURN
464 IF B
=0 THEN GOTO DO_NTH_DONE
473 IF AA
=0 THEN R
=0:RETURN
474 IF Z
%(AA
,1)=0 THEN R
=0
475 IF Z
%(AA
,1)<>0 THEN R
=AA
+1:GOSUB DEREF_R
476 IF R
<>0 THEN Z
%(R
,0)=Z
%(R
,0)+32
479 IF AA
=0 THEN R
=3:Z
%(R
,0)=Z
%(R
,0)+32:RETURN
480 IF Z
%(AA
,1)=0 THEN A
=AA
481 IF Z
%(AA
,1)<>0 THEN A
=Z
%(AA
,1)
482 T
=6:GOSUB FORCE_SEQ_TYPE
486 IF Z
%(AA
,1)=0 THEN R
=2
495 REM remove existing metadata first
496 IF T
>=16 THEN AA
=Z
%(AA
,1):GOTO DO_WITH_META
497 T
=T
+16:L
=AA
:N
=AB
:GOSUB ALLOC
500 IF (Z
%(AA
,0)AND31
)<16 THEN R
=0:RETURN
505 T
=12:L
=AA
:GOSUB ALLOC
509 IF (Z
%(AA
,0)AND31
)=12 THEN R
=2
512 R
=Z
%(AA
,1):GOSUB DEREF_R
517 REM release current value
518 AY
=Z
%(AA
,1):GOSUB RELEASE
519 REM inc ref by 2 for atom ownership and since we are returning it
526 REM P1=ZT:P2=-1:GOSUB PR_MEMORY
528 REM DO_PR_MEMORY_SUMMARY:
529 REM GOSUB PR_MEMORY_SUMMARY
541 INIT_CORE_SET_FUNCTION:
542 GOSUB NATIVE_FUNCTION
548 REM create the environment mapping
549 REM must match DO_FUNCTION mappings
551 K
$="=":A=1:GOSUB INIT_CORE_SET_FUNCTION
552 K
$="throw":A=2:GOSUB INIT_CORE_SET_FUNCTION
553 K
$="nil?":A=3:GOSUB INIT_CORE_SET_FUNCTION
554 K
$="true?":A=4:GOSUB INIT_CORE_SET_FUNCTION
555 K
$="false?":A=5:GOSUB INIT_CORE_SET_FUNCTION
556 K
$="string?":A=6:GOSUB INIT_CORE_SET_FUNCTION
557 K
$="symbol":A=7:GOSUB INIT_CORE_SET_FUNCTION
558 K
$="symbol?":A=8:GOSUB INIT_CORE_SET_FUNCTION
559 K
$="keyword":A=9:GOSUB INIT_CORE_SET_FUNCTION
560 K
$="keyword?":A=10:GOSUB INIT_CORE_SET_FUNCTION
562 K
$="pr-str":A=11:GOSUB INIT_CORE_SET_FUNCTION
563 K
$="str":A=12:GOSUB INIT_CORE_SET_FUNCTION
564 K
$="prn":A=13:GOSUB INIT_CORE_SET_FUNCTION
565 K
$="println":A=14:GOSUB INIT_CORE_SET_FUNCTION
566 K
$="read-string":A=15:GOSUB INIT_CORE_SET_FUNCTION
567 K
$="readline":A=16:GOSUB INIT_CORE_SET_FUNCTION
568 K
$="slurp":A=17:GOSUB INIT_CORE_SET_FUNCTION
570 K
$="<":A=18:GOSUB INIT_CORE_SET_FUNCTION
571 K
$="<=":A=19:GOSUB INIT_CORE_SET_FUNCTION
572 K
$=">":A=20:GOSUB INIT_CORE_SET_FUNCTION
573 K
$=">=":A=21:GOSUB INIT_CORE_SET_FUNCTION
574 K
$="+":A=22:GOSUB INIT_CORE_SET_FUNCTION
575 K
$="-":A=23:GOSUB INIT_CORE_SET_FUNCTION
576 K
$="*":A=24:GOSUB INIT_CORE_SET_FUNCTION
577 K
$="/":A=25:GOSUB INIT_CORE_SET_FUNCTION
578 K
$="time-ms":A=26:GOSUB INIT_CORE_SET_FUNCTION
580 K
$="list":A=27:GOSUB INIT_CORE_SET_FUNCTION
581 K
$="list?":A=28:GOSUB INIT_CORE_SET_FUNCTION
582 K
$="vector":A=29:GOSUB INIT_CORE_SET_FUNCTION
583 K
$="vector?":A=30:GOSUB INIT_CORE_SET_FUNCTION
584 K
$="hash-map":A=31:GOSUB INIT_CORE_SET_FUNCTION
585 K
$="map?":A=32:GOSUB INIT_CORE_SET_FUNCTION
586 K
$="assoc":A=33:GOSUB INIT_CORE_SET_FUNCTION
587 K
$="dissoc":A=34:GOSUB INIT_CORE_SET_FUNCTION
588 K
$="get":A=35:GOSUB INIT_CORE_SET_FUNCTION
589 K
$="contains?":A=36:GOSUB INIT_CORE_SET_FUNCTION
590 K
$="keys":A=37:GOSUB INIT_CORE_SET_FUNCTION
591 K
$="vals":A=38:GOSUB INIT_CORE_SET_FUNCTION
593 K
$="sequential?":A=39:GOSUB INIT_CORE_SET_FUNCTION
594 K
$="cons":A=40:GOSUB INIT_CORE_SET_FUNCTION
595 K
$="concat":A=41:GOSUB INIT_CORE_SET_FUNCTION
596 K
$="nth":A=42:GOSUB INIT_CORE_SET_FUNCTION
597 K
$="first":A=43:GOSUB INIT_CORE_SET_FUNCTION
598 K
$="rest":A=44:GOSUB INIT_CORE_SET_FUNCTION
599 K
$="empty?":A=45:GOSUB INIT_CORE_SET_FUNCTION
600 K
$="count":A=46:GOSUB INIT_CORE_SET_FUNCTION
602 REM K$="conj":A=47:GOSUB INIT_CORE_SET_FUNCTION
603 REM K$="seq":A=48:GOSUB INIT_CORE_SET_FUNCTION
605 K
$="with-meta":A=49:GOSUB INIT_CORE_SET_FUNCTION
606 K
$="meta":A=50:GOSUB INIT_CORE_SET_FUNCTION
607 K
$="atom":A=51:GOSUB INIT_CORE_SET_FUNCTION
608 K
$="atom?":A=52:GOSUB INIT_CORE_SET_FUNCTION
609 K
$="deref":A=53:GOSUB INIT_CORE_SET_FUNCTION
610 K
$="reset!":A=54:GOSUB INIT_CORE_SET_FUNCTION
612 K
$="eval":A=55:GOSUB INIT_CORE_SET_FUNCTION
613 K
$="read-file":A=56:GOSUB INIT_CORE_SET_FUNCTION
615 REM these are in DO_TCO_FUNCTION
616 K
$="apply":A=61:GOSUB INIT_CORE_SET_FUNCTION
617 K
$="map":A=62:GOSUB INIT_CORE_SET_FUNCTION
618 K
$="swap!":A=63:GOSUB INIT_CORE_SET_FUNCTION