13 REM EQUAL_Q(A, B) -> R
15 ED
=0: REM recursion depth
16 R
=-1: REM return value
27 IF T
>5 AND T
<8 AND T2
>5 AND T2
<8 THEN GOTO EQUAL_Q_SEQ
28 IF T
=8 AND T2
=8 THEN GOTO EQUAL_Q_HM
30 IF T
<>T2
OR Z
%(A
+1)<>Z
%(B
+1) THEN R
=0
34 IF Z
%(A
+1)=0 AND Z
%(B
+1)=0 THEN GOTO EQUAL_Q_DONE
35 IF Z
%(A
+1)=0 OR Z
%(B
+1)=0 THEN R
=0:GOTO EQUAL_Q_DONE
37 REM compare the elements
42 REM next elements of the sequences
55 REM pop current A and B
59 IF R
>-1 AND ED
>0 THEN GOTO EQUAL_Q_DONE
: REM unwind
60 IF ED
=0 AND R
=-1 THEN R
=1
62 GOTO EQUAL_Q_SEQ_CONTINUE
66 REM STRING(B$, T) -> R
67 REM intern string and allocate reference (return Z% index)
69 IF S
=0 THEN GOTO STRING_NOT_FOUND
71 REM search for matching string in S$
74 IF I
>S
-1 THEN GOTO STRING_NOT_FOUND
75 IF S
%(I
)>0 AND B
$=S$(I) THEN GOTO STRING_DONE
82 REM TODO: don't search core function names (store position)
83 IF I
=-1 THEN GOTO STRING_NEW
84 IF S
%(I
)=0 THEN GOTO STRING_SET
86 GOTO STRING_FIND_GAP_LOOP
102 REM REPLACE(R$, S1$, S2$) -> R$
110 C
$=MID$(T3$,I,LEN(S1$))
111 IF C
$=S1$ THEN R
$=R$+S2$:I=I+LEN(S1$)
112 IF C
$<>S1$ THEN R
$=R$+MID$(T3$,I,1):I=I+1
116 REM sequence functions
118 REM FORCE_SEQ_TYPE(A,T) -> R
120 REM if it's already the right type, inc ref cnt and return it
121 IF (Z
%(A
)AND 31)=T
THEN R
=A
:GOTO INC_REF_R
122 REM if it's empty, return the empty sequence match T
123 IF A
<16 THEN R
=(T
-4)*3:GOTO INC_REF_R
124 REM otherwise, copy first element to turn it into correct type
125 B
=Z
%(A
+2): REM value to copy
126 L
=Z
%(A
+1):M
=B
:GOSUB ALLOC
: REM T already set
127 IF Z
%(A
+1)=0 THEN RETURN
130 REM MAP_LOOP_START(T):
131 REM - setup stack for map loop
133 REM point to empty sequence to start off
134 R
=(T
-4)*3: REM calculate location of empty seq
136 GOSUB PUSH_R
: REM push return ptr
137 GOSUB PUSH_R
: REM push empty ptr
138 GOSUB PUSH_R
: REM push current ptr
141 REM MAP_LOOP_UPDATE(C,M):
142 REM MAP_LOOP_UPDATE(C,M,N):
143 REM - called after M (and N if T=8) are set
144 REM - C indicates whether to free M (and N if T=8)
145 REM - update the structure of the return sequence
147 GOSUB PEEK_Q_1
:L
=Q
: REM empty ptr
149 GOSUB ALLOC
: REM allocate new sequence element
151 REM sequence took ownership
153 IF C
THEN AY
=M
:GOSUB RELEASE
154 IF C
AND T
=8 THEN AY
=N
:GOSUB RELEASE
156 REM if not first element, set current next to point to new element
158 IF Q
>14 THEN Z
%(Q
+1)=R
159 REM if first element, set return to new element
160 IF Q
<15 THEN Q
=R
:GOSUB PUT_Q_2
161 Q
=R
:GOSUB PUT_Q
: REM update current ptr to new element
165 REM MAP_LOOP_DONE() -> R
166 REM - cleanup stack and set return value
168 GOSUB POP_Q
: REM pop current ptr
169 GOSUB POP_Q
: REM pop empty ptr
170 GOSUB POP_R
: REM pop return ptr
184 IF Z
%(A
+1)=0 THEN R
=1
188 REM - returns length of list, not a Z% index
194 IF Z
%(A
+1)<>0 THEN A
=Z
%(A
+1):GOTO DO_COUNT_LOOP
200 REM TODO check that actually a list/vector
201 IF Z
%(A
+1)=0 THEN R
=0:RETURN: REM empty seq, return nil
204 IF Z
%(A
+1)=0 THEN GOTO LAST_DONE
: REM end, return previous value
205 W
=A
: REM current becomes previous entry
206 A
=Z
%(A
+1): REM next entry
212 REM SLICE(A,B,C) -> R
213 REM make copy of sequence A from index B to C
214 REM returns R6 as reference to last element of slice before empty
215 REM returns A as next element following slice (of original)
218 R
=6: REM always a list
220 R6
=-1: REM last list element before empty
221 W
=R
: REM temporary for return as R
222 REM advance A to position B
224 IF I
<B
AND Z
%(A
+1)<>0 THEN A
=Z
%(A
+1):I
=I
+1:GOTO SLICE_FIND_B
226 REM if current position is C, then return
227 IF C
<>-1 AND I
>=C
THEN R
=W
:RETURN
228 REM if we reached end of A, then return
229 IF Z
%(A
+1)=0 THEN R
=W
:RETURN
230 REM allocate new list element with copied value
231 T
=6:L
=6:M
=Z
%(A
+2):GOSUB ALLOC
232 REM sequence took ownership
234 REM if not first element, set last to point to new element
235 IF R6
>-1 THEN Z
%(R6
+1)=R
236 REM if first element, set return value to new element
238 R6
=R
: REM update last list element
239 REM advance to next element of A
246 REM last element is 3 (empty list), second element is A
247 T
=6:L
=6:M
=A
:GOSUB ALLOC
249 REM first element is B
250 T
=6:L
=R
:M
=B
:GOSUB ALLOC
251 AY
=L
:GOSUB RELEASE
: REM new list takes ownership of previous
255 REM LIST3(C,B,A) -> R
259 REM first element is C
260 T
=6:L
=R
:M
=C
:GOSUB ALLOC
261 AY
=L
:GOSUB RELEASE
: REM new list takes ownership of previous
266 REM hashmap functions
270 REM just point to static empty hash-map
274 REM ASSOC1(H, K, C) -> R
276 REM create key/value entry
277 T
=8:L
=H
:M
=K
:N
=C
:GOSUB ALLOC
278 AY
=L
:GOSUB RELEASE
: REM we took ownership of previous hashmap
281 REM ASSOC1_S(H, B$, C) -> R
283 REM add the key string
286 AY
=K
:GOSUB RELEASE
: REM map took ownership of key
289 REM HASHMAP_GET(H, K) -> R
290 REM - returns R3 with whether we found it or not
292 B
$=S$(Z%(K+1)): REM search key string
293 R3
=0: REM whether found or not (for HASHMAP_CONTAINS)
296 REM no matching key found
297 IF Z
%(H
+1)=0 THEN R
=0:RETURN
298 REM get search string is equal to key string we found it
299 IF B
$=S$(Z%(Z%(H+2)+1)) THEN R3
=1:R
=Z
%(H
+3):RETURN
300 REM skip to next key/value
302 GOTO HASHMAP_GET_LOOP
304 REM HASHMAP_CONTAINS(H, K) -> R