1 REM APPLY should really be in types.in.bas but it is here because it
2 REM calls DO_TCO_FUNCTION so it will cause syntax errors for steps1-3
3 REM if it is in types.in.bas because there are unresolved labels.
7 REM - call using GOTO and with return label/address on the stack
9 REM if metadata, get the actual object
10 IF (Z
%(F
,0)AND31
)>=16 THEN F
=Z
%(F
,1)
12 IF (Z
%(F
,0)AND31
)=9 THEN GOTO APPLY_FUNCTION
13 IF (Z
%(F
,0)AND31
)=10 THEN GOTO APPLY_MAL_FUNCTION
14 IF (Z
%(F
,0)AND31
)=11 THEN GOTO APPLY_MAL_FUNCTION
18 IF Z
%(F
,1)<60 THEN GOSUB DO_FUNCTION
:GOTO APPLY_DONE
19 REM for recur functions (apply, map, swap!), use GOTO
20 IF Z
%(F
,1)>60 THEN CALL DO_TCO_FUNCTION
24 X
=X
+1:X
%(X
)=E
: REM save the current environment
26 REM create new environ using env and params stored in the
27 REM function and bind the params to the apply arguments
28 O
=Z
%(F
+1,1):BI
=Z
%(F
+1,0):EX
=AR
:GOSUB ENV_NEW_BINDS
30 A
=Z
%(F
,1):E
=R
:CALL EVAL
32 AY
=E
:GOSUB RELEASE
: REM release the new environment
34 E
=X
%(X
):X
=X
-1: REM pop/restore the saved environment
40 REM DO_TCO_FUNCTION(F, AR)
44 REM Get argument values
45 R
=AR
+1:GOSUB DEREF_R
:AA
=R
46 R
=Z
%(AR
,1)+1:GOSUB DEREF_R
:AB
=R
48 ON FF
-60 GOTO DO_APPLY
,DO_MAP
,DO_SWAP_BANG
56 REM no intermediate args, but not a list, so convert it first
57 IF R4
<=1 AND (Z
%(A
,0)AND31
)<>6 THEN T
=6:GOSUB FORCE_SEQ_TYPE
:GOTO DO_APPLY_2
58 REM no intermediate args, just call APPLY directly
59 IF R4
<=1 THEN GOTO DO_APPLY_1
61 REM prepend intermediate args to final args element
62 A
=AR
:B
=0:C
=R4
-1:GOSUB SLICE
63 REM release the terminator of new list (we skip over it)
64 AY
=Z
%(R6
,1):GOSUB RELEASE
65 REM attach end of slice to final args element
67 Z
%(Z
%(A
+1,1),0)=Z
%(Z
%(A
+1,1),0)+32
74 GOTO DO_TCO_FUNCTION_DONE
77 X
=X
+1:X
%(X
)=R
: REM push/save new args for release
81 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
: REM pop/release new args
82 GOTO DO_TCO_FUNCTION_DONE
87 REM first result list element
88 T
=6:L
=0:N
=0:GOSUB ALLOC
90 REM push future return val, prior entry, F and AB
91 X
=X
+4:X
%(X
-3)=R
:X
%(X
-2)=0:X
%(X
-1)=F
:X
%(X
)=AB
94 REM set previous to current if not the first element
95 IF X
%(X
-2)<>0 THEN Z
%(X
%(X
-2),1)=R
96 REM update previous reference to current
99 IF Z
%(AB
,1)=0 THEN GOTO DO_MAP_DONE
101 REM create argument list for apply call
103 REM inc ref cnt of referred argument
104 T
=6:L
=3:N
=Z
%(AB
+1,1):GOSUB ALLOC
106 REM push argument list
111 REM pop apply args are release them
112 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
114 REM set the result value
120 REM update AB to next source element
124 REM allocate next element
125 T
=6:L
=0:N
=0:GOSUB ALLOC
132 REM pop everything off stack
134 GOTO DO_TCO_FUNCTION_DONE
140 REM add atom to front of the args list
141 T
=6:L
=Z
%(Z
%(AR
,1),1):N
=Z
%(AA
,1):GOSUB ALLOC
: REM cons
144 REM push args for release after
155 REM pop and release args
156 AY
=X
%(X
):X
=X
-1:GOSUB RELEASE
158 REM use reset to update the value
159 AB
=R
:GOSUB DO_RESET_BANG
161 REM but decrease ref cnt of return by 1 (not sure why)
164 GOTO DO_TCO_FUNCTION_DONE
166 DO_TCO_FUNCTION_DONE:
170 REM DO_FUNCTION(F, AR)
172 REM Get the function number
175 REM Get argument values
176 R
=AR
+1:GOSUB DEREF_R
:AA
=R
177 R
=Z
%(AR
,1)+1:GOSUB DEREF_R
:AB
=R
179 REM Switch on the function number
180 IF FF
>59 THEN ER
=-1:ER
$="unknown function"+STR$(FF):RETURN
181 ON FF/10+1 GOTO DO_1_9,DO_10_19,DO_20_29,DO_30_39,DO_40_49,DO_50_56
184 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
186 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
188 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
190 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
192 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
194 ON FF-49 GOTO DO_META,DO_ATOM,DO_ATOM_Q,DO_DEREF,DO_RESET_BANG,DO_EVAL,DO_READ_FILE
197 A=AA:B=AB:GOSUB EQUAL_Q
219 IF (Z%(AA,0)AND31)<>4 THEN RETURN
220 IF MID$(S$(Z%(AA,1)),1,1)=CHR$(127) THEN RETURN
224 T=5:L=Z%(AA,1):GOSUB ALLOC
228 IF (Z%(AA,0)AND31)=5 THEN R=2
233 IF MID$(AS$,1,1)<>CHR$(127) THEN AS$=CHR$(127)+AS$
239 IF (Z%(AA,0)AND31)<>4 THEN RETURN
240 IF MID$(S$(Z%(AA,1)),1,1)<>CHR$(127) THEN RETURN
245 AZ=AR:PR=1:SE$=" ":GOSUB PR_STR_SEQ
246 AS$=R$:T=4:GOSUB STRING
249 AZ
=AR
:PR
=0:SE
$="":GOSUB PR_STR_SEQ
250 AS$=R$:T=4:GOSUB STRING
253 AZ
=AR
:PR
=1:SE
$=" ":GOSUB PR_STR_SEQ
258 AZ=AR:PR=0:SE$=" ":GOSUB PR_STR_SEQ
267 A
$=S$(Z%(AA,1)):GOSUB READLINE
268 IF EOF
=1 THEN EOF
=0:R
=0:RETURN
269 AS$=R$:T=4:GOSUB STRING
273 REM OPEN 1,8,2,S$(Z%(AA,1))+",SEQ,R"
274 REM OPEN 1,8,2,S$(Z%(AA,1))
275 OPEN
1,8,0,S
$(Z%(AA,1))
279 IF ASC(A
$)=10 THEN R
$=R$+CHR$(13)
280 IF (ASC(A
$)<>10) AND (A
$<>"") THEN R
$=R$+A$
281 IF (ST
AND 64) THEN GOTO DO_SLURP_DONE
282 IF (ST
AND 255) THEN ER
=-1:ER
$="File read
error "+STR$(ST):RETURN
286 AS$=R$:T=4:GOSUB STRING
291 IF Z%(AA,1)<Z%(AB,1) THEN R=2
295 IF Z%(AA,1)<=Z%(AB,1) THEN R=2
299 IF Z%(AA,1)>Z%(AB,1) THEN R=2
303 IF Z%(AA,1)>=Z%(AB,1) THEN R=2
307 T=2:L=Z%(AA,1)+Z%(AB,1):GOSUB ALLOC
310 T=2:L=Z%(AA,1)-Z%(AB,1):GOSUB ALLOC
313 T=2:L=Z%(AA,1)*Z%(AB,1):GOSUB ALLOC
316 T=2:L=Z%(AA,1)/Z%(AB,1):GOSUB ALLOC
319 T=2:L=INT((TI-BT)*16.667):GOSUB ALLOC
328 R=R+1: REM map to mal false/true
331 A=AR:T=7:GOSUB FORCE_SEQ_TYPE
335 IF (Z%(AA,0)AND31)=7 THEN R=2
338 A=AR:T=8:GOSUB FORCE_SEQ_TYPE
342 IF (Z%(AA,0)AND31)=8 THEN R=2
348 R=AR+1:GOSUB DEREF_R:K=R
349 R=Z%(AR,1)+1:GOSUB DEREF_R:V=R
353 IF AR=0 OR Z%(AR,1)=0 THEN RETURN
356 IF AA=0 THEN R=0:RETURN
357 H=AA:K=AB:GOSUB HASHMAP_GET
362 H=AA:K=AB:GOSUB HASHMAP_CONTAINS
370 REM first result list element
371 T=6:L=0:N=0:GOSUB ALLOC:T2=R
374 IF AA=0 OR Z%(AA,1)=0 THEN R=T2:RETURN
378 REM inc ref cnt of referred argument
382 T1=R: REM save previous
383 REM allocate next element
384 T=6:L=0:N=0:GOSUB ALLOC
385 REM point previous element to this one
388 IF Z%(Z%(AA,1),1)=0 THEN R=T2:RETURN
392 GOTO DO_KEYS_VALS_LOOP
396 IF (Z%(AA,0)AND31)=6 OR (Z%(AA,0)AND31)=7 THEN R=2
399 T=6:L=AB:N=AA:GOSUB ALLOC
402 REM if empty arguments, return empty list
403 IF Z%(AR,1)=0 THEN R=3:Z%(R,0)=Z%(R,0)+32:RETURN
406 IF Z%(Z%(AR,1),1)<>0 THEN GOTO DO_CONCAT_MULT
407 REM force to list type
408 A=AA:T=6:GOSUB FORCE_SEQ_TYPE
411 REM multiple arguments
413 CZ=X: REM save current stack position
414 REM push arguments onto the stack
417 X=X+1:X%(X)=R: REM push sequence
419 IF Z%(AR,1)<>0 THEN GOTO DO_CONCAT_STACK
421 REM pop last argument as our seq to prepend to
423 REM last arg/seq is not copied so we need to inc ref to it
426 IF X=CZ THEN R=AB:RETURN
427 AA=X%(X):X=X-1: REM pop off next seq to prepend
428 IF Z%(AA,1)=0 THEN GOTO DO_CONCAT_LOOP: REM skip empty seqs
429 A=AA:B=0:C=-1:GOSUB SLICE
431 REM release the terminator of new list (we skip over it)
432 AY=Z%(R6,1):GOSUB RELEASE
433 REM attach new list element before terminator (last actual
434 REM element to the next sequence
442 IF R<=B THEN R=0:ER=-1:ER$="nth: index out of range":RETURN
444 IF B
=0 THEN GOTO DO_NTH_DONE
453 IF AA
=0 THEN R
=0:RETURN
454 IF Z
%(AA
,1)=0 THEN R
=0
455 IF Z
%(AA
,1)<>0 THEN R
=AA
+1:GOSUB DEREF_R
456 IF R
<>0 THEN Z
%(R
,0)=Z
%(R
,0)+32
459 IF AA
=0 THEN R
=3:Z
%(R
,0)=Z
%(R
,0)+32:RETURN
460 IF Z
%(AA
,1)=0 THEN A
=AA
461 IF Z
%(AA
,1)<>0 THEN A
=Z
%(AA
,1)
462 T
=6:GOSUB FORCE_SEQ_TYPE
466 IF Z
%(AA
,1)=0 THEN R
=2
475 REM remove existing metadata first
476 IF T
>=16 THEN AA
=Z
%(AA
,1):GOTO DO_WITH_META
477 T
=T
+16:L
=AA
:N
=AB
:GOSUB ALLOC
480 IF (Z
%(AA
,0)AND31
)<16 THEN R
=0:RETURN
485 T
=12:L
=AA
:GOSUB ALLOC
489 IF (Z
%(AA
,0)AND31
)=12 THEN R
=2
492 R
=Z
%(AA
,1):GOSUB DEREF_R
497 REM release current value
498 AY
=Z
%(AA
,1):GOSUB RELEASE
499 REM inc ref by 2 for atom ownership and since we are returning it
506 REM P1=ZT:P2=-1:GOSUB PR_MEMORY
508 REM DO_PR_MEMORY_SUMMARY:
509 REM GOSUB PR_MEMORY_SUMMARY
521 INIT_CORE_SET_FUNCTION:
522 GOSUB NATIVE_FUNCTION
528 REM create the environment mapping
529 REM must match DO_FUNCTION mappings
531 K
$="=":A=1:GOSUB INIT_CORE_SET_FUNCTION
532 K
$="throw":A=2:GOSUB INIT_CORE_SET_FUNCTION
533 K
$="nil?":A=3:GOSUB INIT_CORE_SET_FUNCTION
534 K
$="true?":A=4:GOSUB INIT_CORE_SET_FUNCTION
535 K
$="false?":A=5:GOSUB INIT_CORE_SET_FUNCTION
536 K
$="string?":A=6:GOSUB INIT_CORE_SET_FUNCTION
537 K
$="symbol":A=7:GOSUB INIT_CORE_SET_FUNCTION
538 K
$="symbol?":A=8:GOSUB INIT_CORE_SET_FUNCTION
539 K
$="keyword":A=9:GOSUB INIT_CORE_SET_FUNCTION
540 K
$="keyword?":A=10:GOSUB INIT_CORE_SET_FUNCTION
542 K
$="pr-str":A=11:GOSUB INIT_CORE_SET_FUNCTION
543 K
$="str":A=12:GOSUB INIT_CORE_SET_FUNCTION
544 K
$="prn":A=13:GOSUB INIT_CORE_SET_FUNCTION
545 K
$="println":A=14:GOSUB INIT_CORE_SET_FUNCTION
546 K
$="read-string":A=15:GOSUB INIT_CORE_SET_FUNCTION
547 K
$="readline":A=16:GOSUB INIT_CORE_SET_FUNCTION
548 K
$="slurp":A=17:GOSUB INIT_CORE_SET_FUNCTION
550 K
$="<":A=18:GOSUB INIT_CORE_SET_FUNCTION
551 K
$="<=":A=19:GOSUB INIT_CORE_SET_FUNCTION
552 K
$=">":A=20:GOSUB INIT_CORE_SET_FUNCTION
553 K
$=">=":A=21:GOSUB INIT_CORE_SET_FUNCTION
554 K
$="+":A=22:GOSUB INIT_CORE_SET_FUNCTION
555 K
$="-":A=23:GOSUB INIT_CORE_SET_FUNCTION
556 K
$="*":A=24:GOSUB INIT_CORE_SET_FUNCTION
557 K
$="/":A=25:GOSUB INIT_CORE_SET_FUNCTION
558 K
$="time-ms":A=26:GOSUB INIT_CORE_SET_FUNCTION
560 K
$="list":A=27:GOSUB INIT_CORE_SET_FUNCTION
561 K
$="list?":A=28:GOSUB INIT_CORE_SET_FUNCTION
562 K
$="vector":A=29:GOSUB INIT_CORE_SET_FUNCTION
563 K
$="vector?":A=30:GOSUB INIT_CORE_SET_FUNCTION
564 K
$="hash-map":A=31:GOSUB INIT_CORE_SET_FUNCTION
565 K
$="map?":A=32:GOSUB INIT_CORE_SET_FUNCTION
566 K
$="assoc":A=33:GOSUB INIT_CORE_SET_FUNCTION
567 K
$="dissoc":A=34:GOSUB INIT_CORE_SET_FUNCTION
568 K
$="get":A=35:GOSUB INIT_CORE_SET_FUNCTION
569 K
$="contains?":A=36:GOSUB INIT_CORE_SET_FUNCTION
570 K
$="keys":A=37:GOSUB INIT_CORE_SET_FUNCTION
571 K
$="vals":A=38:GOSUB INIT_CORE_SET_FUNCTION
573 K
$="sequential?":A=39:GOSUB INIT_CORE_SET_FUNCTION
574 K
$="cons":A=40:GOSUB INIT_CORE_SET_FUNCTION
575 K
$="concat":A=41:GOSUB INIT_CORE_SET_FUNCTION
576 K
$="nth":A=42:GOSUB INIT_CORE_SET_FUNCTION
577 K
$="first":A=43:GOSUB INIT_CORE_SET_FUNCTION
578 K
$="rest":A=44:GOSUB INIT_CORE_SET_FUNCTION
579 K
$="empty?":A=45:GOSUB INIT_CORE_SET_FUNCTION
580 K
$="count":A=46:GOSUB INIT_CORE_SET_FUNCTION
582 REM K$="conj":A=47:GOSUB INIT_CORE_SET_FUNCTION
583 REM K$="seq":A=48:GOSUB INIT_CORE_SET_FUNCTION
585 K
$="with-meta":A=49:GOSUB INIT_CORE_SET_FUNCTION
586 K
$="meta":A=50:GOSUB INIT_CORE_SET_FUNCTION
587 K
$="atom":A=51:GOSUB INIT_CORE_SET_FUNCTION
588 K
$="atom?":A=52:GOSUB INIT_CORE_SET_FUNCTION
589 K
$="deref":A=53:GOSUB INIT_CORE_SET_FUNCTION
590 K
$="reset!":A=54:GOSUB INIT_CORE_SET_FUNCTION
592 K
$="eval":A=55:GOSUB INIT_CORE_SET_FUNCTION
593 K
$="read-file":A=56:GOSUB INIT_CORE_SET_FUNCTION
595 REM these are in DO_TCO_FUNCTION
596 K
$="apply":A=61:GOSUB INIT_CORE_SET_FUNCTION
597 K
$="map":A=62:GOSUB INIT_CORE_SET_FUNCTION
598 K
$="swap!":A=63:GOSUB INIT_CORE_SET_FUNCTION