Commit | Line | Data |
---|---|---|
b7b1787f JM |
1 | REM Z 0 -> 1 |
2 | REM nil 0 -> (unused) | |
3 | REM boolean 1 -> 0: false, 1: true | |
4 | REM integer 2 -> int value | |
5 | REM float 3 -> ??? | |
6 | REM string/kw 4 -> ZS$ index | |
7 | REM symbol 5 -> ZS$ index | |
60270667 | 8 | REM list next/val 6 -> next Z% index (0 for last) |
b7b1787f | 9 | REM followed by value (unless empty) |
60270667 | 10 | REM vector next/val 7 -> next Z% index (0 for last) |
b7b1787f | 11 | REM followed by value (unless empty) |
60270667 | 12 | REM hashmap next/val 8 -> next Z% index (0 for last) |
b7b1787f | 13 | REM followed by key or value (alternating) |
60270667 | 14 | REM function 9 -> function index |
4b84a23b JM |
15 | REM mal function 10 -> body AST Z% index |
16 | REM followed by param and env Z% index | |
60270667 | 17 | REM atom 11 -> Z% index |
4b84a23b JM |
18 | REM environment 13 -> data/hashmap Z% index |
19 | REM followed by 13 and outer Z% index (-1 for none) | |
20 | REM reference/ptr 14 -> Z% index / or 0 | |
21 | REM next free ptr 15 -> Z% index / or 0 | |
11f94d2e JM |
22 | |
23 | INIT_MEMORY: | |
b7b1787f | 24 | T%=FRE(0) |
4b84a23b JM |
25 | |
26 | S1%=3072: REM Z% (boxed memory) size (X2) | |
27 | REM S1%=4096: REM Z% (boxed memory) size (X2) | |
241d5d57 | 28 | S2%=256: REM ZS% (string memory) size |
60270667 | 29 | S3%=256: REM ZZ% (call stack) size |
412e7348 | 30 | S4%=128: REM ZR% (release stack) size |
b7b1787f | 31 | |
11f94d2e JM |
32 | REM global error state |
33 | ER%=0 | |
34 | ER$="" | |
35 | ||
b7b1787f JM |
36 | REM boxed element memory |
37 | DIM Z%(S1%,1): REM TYPE ARRAY | |
11f94d2e JM |
38 | |
39 | REM Predefine nil, false, true | |
b7b1787f | 40 | Z%(0,0) = 0 |
241d5d57 | 41 | Z%(0,1) = 0 |
b7b1787f JM |
42 | Z%(1,0) = 1 |
43 | Z%(1,1) = 0 | |
44 | Z%(2,0) = 1 | |
45 | Z%(2,1) = 1 | |
4b84a23b JM |
46 | |
47 | REM start of unused memory | |
11f94d2e JM |
48 | ZI%=3 |
49 | ||
4b84a23b JM |
50 | REM start of free list |
51 | ZK%=3 | |
52 | ||
b7b1787f | 53 | REM string memory storage |
11f94d2e | 54 | ZJ%=0 |
b7b1787f JM |
55 | DIM ZS$(S2%) |
56 | ||
60270667 | 57 | REM call/logic stack |
b7b1787f | 58 | ZL%=-1 |
60270667 | 59 | DIM ZZ%(S3%): REM stack of Z% indexes |
b7b1787f | 60 | |
4b84a23b JM |
61 | REM pending release stack |
62 | ZM%=-1 | |
63 | DIM ZR%(S4%): REM stack of Z% indexes | |
64 | ||
b7b1787f JM |
65 | REM PRINT "Lisp data memory: " + STR$(T%-FRE(0)) |
66 | REM PRINT "Interpreter working memory: " + STR$(FRE(0)) | |
67 | RETURN | |
68 | ||
4b84a23b JM |
69 | REM memory functions |
70 | ||
71 | REM ALLOC(SZ%) -> R% | |
72 | ALLOC: | |
73 | REM PRINT "ALLOC SZ%: "+STR$(SZ%)+", ZK%: "+STR$(ZK%) | |
74 | U3%=ZK% | |
75 | U4%=ZK% | |
76 | ALLOC_LOOP: | |
77 | IF U4%=ZI% THEN GOTO ALLOC_UNUSED | |
78 | REM TODO sanity check that type is 15 | |
79 | IF ((Z%(U4%,0)AND-16)/16)=SZ% THEN GOTO ALLOC_MIDDLE | |
80 | REM PRINT "ALLOC search: U3%: "+STR$(U3%)+", U4%: "+STR$(U4%) | |
81 | U3%=U4%: REM previous set to current | |
82 | U4%=Z%(U4%,1): REM current set to next | |
83 | GOTO ALLOC_LOOP | |
84 | ALLOC_MIDDLE: | |
85 | REM PRINT "ALLOC_MIDDLE: U3%: "+STR$(U3%)+", U4%: "+STR$(U4%) | |
86 | R%=U4% | |
87 | REM set free pointer (ZK%) to next free | |
88 | IF U4%=ZK% THEN ZK%=Z%(U4%,1) | |
89 | REM set previous free to next free | |
90 | IF U4%<>ZK% THEN Z%(U3%,1)=Z%(U4%,1) | |
91 | RETURN | |
92 | ALLOC_UNUSED: | |
93 | REM PRINT "ALLOC_UNUSED ZI%: "+STR$(ZI%)+", U3%: "+STR$(U3%)+", U4%: "+STR$(U4%) | |
94 | R%=U4% | |
95 | ZI%=ZI%+SZ% | |
96 | IF U3%=U4% THEN ZK%=ZI% | |
97 | REM set previous free to new memory top | |
98 | IF U3%<>U4% THEN Z%(U3%,1)=ZI% | |
99 | RETURN | |
100 | ||
101 | REM FREE(AY%, SZ%) -> nil | |
102 | FREE: | |
103 | REM assumes reference count cleanup already (see RELEASE) | |
104 | Z%(AY%,0) = (SZ%*16)+15: REM set type(15) and size | |
105 | Z%(AY%,1) = ZK% | |
106 | IF SZ%>=2 THEN Z%(AY%+1,0)=0 | |
107 | IF SZ%>=2 THEN Z%(AY%+1,1)=0 | |
108 | IF SZ%>=3 THEN Z%(AY%+2,0)=0 | |
109 | IF SZ%>=3 THEN Z%(AY%+2,1)=0 | |
110 | ZK%=AY% | |
111 | RETURN | |
112 | ||
113 | ||
114 | REM RELEASE(AY%) -> nil | |
412e7348 | 115 | REM R% should not be affected by this call |
4b84a23b JM |
116 | RELEASE: |
117 | RC%=0 | |
118 | ||
119 | GOTO RELEASE_ONE | |
120 | ||
121 | RELEASE_TOP: | |
122 | ||
123 | IF RC%=0 THEN RETURN | |
124 | ||
125 | REM pop next object to release, decrease remaining count | |
126 | AY%=ZZ%(ZL%): ZL%=ZL%-1 | |
127 | RC%=RC%-1 | |
128 | ||
129 | RELEASE_ONE: | |
130 | ||
131 | REM nil, false, true | |
132 | IF AY%<3 THEN GOTO RELEASE_TOP | |
133 | ||
412e7348 JM |
134 | U6%=Z%(AY%,0)AND15: REM type |
135 | ||
136 | REM AZ%=AY%: PR%=1: GOSUB PR_STR | |
137 | REM PRINT "RELEASE AY%:"+STR$(AY%)+"["+R$+"] (byte0:"+STR$(Z%(AY%,0))+")" | |
138 | ||
4b84a23b | 139 | REM sanity check not already freed |
412e7348 JM |
140 | IF (U6%)=15 THEN ER%=1: ER$="Free of free memory: " + STR$(AY%): RETURN |
141 | IF Z%(AY%,0)<15 THEN ER%=1: ER$="Free of freed object: " + STR$(AY%): RETURN | |
4b84a23b JM |
142 | |
143 | REM decrease reference count by one | |
144 | Z%(AY%,0)=Z%(AY%,0)-16 | |
145 | ||
146 | REM our reference count is not 0, so don't release | |
147 | IF Z%(AY%,0)>=16 GOTO RELEASE_TOP | |
148 | ||
149 | REM switch on type | |
4b84a23b JM |
150 | IF (U6%<=5) OR (U6%=9) THEN GOTO RELEASE_SIMPLE |
151 | IF (U6%>=6) AND (U6%<=8) THEN GOTO RELEASE_SEQ | |
152 | IF U6%=10 THEN GOTO RELEASE_MAL_FUNCTION | |
153 | IF U6%=13 THEN GOTO RELEASE_ENV | |
154 | IF U6%=14 THEN GOTO RELEASE_REFERENCE | |
155 | IF U6%=15 THEN ER%=1: ER$="RELEASE of already freed: "+STR$(AY%): RETURN | |
156 | ER%=1: ER$="RELEASE not defined for type " + STR$(U6%): RETURN | |
157 | ||
158 | RELEASE_SIMPLE: | |
159 | REM simple type (no recursing), just call FREE on it | |
160 | SZ%=1: GOSUB FREE | |
161 | GOTO RELEASE_TOP | |
162 | RELEASE_SIMPLE_2: | |
163 | REM free the current element and continue | |
164 | SZ%=2: GOSUB FREE | |
165 | GOTO RELEASE_TOP | |
166 | RELEASE_SEQ: | |
167 | IF Z%(AY%,1)=0 THEN GOTO RELEASE_SIMPLE_2 | |
168 | IF Z%(AY%+1,0)<>14 THEN ER%=1: ER$="invalid list value"+STR$(AY%+1): RETURN | |
169 | REM add value and next element to stack | |
170 | RC%=RC%+2: ZL%=ZL%+2: ZZ%(ZL%-1)=Z%(AY%+1,1): ZZ%(ZL%)=Z%(AY%,1) | |
171 | GOTO RELEASE_SIMPLE_2 | |
172 | RELEASE_MAL_FUNCTION: | |
173 | REM add ast, params and environment to stack | |
174 | RC%=RC%+3: ZL%=ZL%+3 | |
175 | ZZ%(ZL%-2)=Z%(AY%,1): ZZ%(ZL%-1)=Z%(AY%+1,0): ZZ%(ZL%)=Z%(AY%+1,1) | |
176 | REM free the current 2 element mal_function and continue | |
177 | SZ%=2: GOSUB FREE | |
178 | GOTO RELEASE_TOP | |
179 | RELEASE_ENV: | |
180 | REM add the hashmap data to the stack | |
181 | RC%=RC%+1: ZL%=ZL%+1: ZZ%(ZL%)=Z%(AY%,1) | |
182 | REM if no outer set | |
183 | IF Z%(AY%+1,1)=-1 THEN GOTO RELEASE_ENV_FREE | |
184 | REM add outer environment to the stack | |
185 | RC%=RC%+1: ZL%=ZL%+1: ZZ%(ZL%)=Z%(AY%+1,1) | |
186 | RELEASE_ENV_FREE: | |
187 | REM free the current 2 element environment and continue | |
188 | SZ%=2: GOSUB FREE | |
189 | GOTO RELEASE_TOP | |
190 | RELEASE_REFERENCE: | |
191 | IF Z%(AY%,1)=0 THEN GOTO RELEASE_SIMPLE | |
192 | REM add the referred element to the stack | |
193 | RC%=RC%+1: ZL%=ZL%+1: ZZ%(ZL%)=Z%(AY%,1) | |
194 | REM free the current element and continue | |
195 | SZ%=1: GOSUB FREE | |
196 | GOTO RELEASE_TOP | |
197 | ||
198 | REM RELEASE_PEND() -> nil | |
199 | RELEASE_PEND: | |
412e7348 | 200 | REM REM IF ER%<>0 THEN RETURN |
4b84a23b | 201 | IF ZM%<0 THEN RETURN |
412e7348 | 202 | REM PRINT "here2 RELEASE_PEND releasing:"+STR$(ZR%(ZM%)) |
4b84a23b JM |
203 | AY%=ZR%(ZM%): GOSUB RELEASE |
204 | ZM%=ZM%-1 | |
205 | GOTO RELEASE_PEND | |
206 | ||
207 | REM DEREF_R(R%) -> R% | |
208 | DEREF_R: | |
209 | IF (Z%(R%,0)AND15)=14 THEN R%=Z%(R%,1): GOTO DEREF_R | |
210 | RETURN | |
211 | ||
212 | REM DEREF_A(A%) -> A% | |
213 | DEREF_A: | |
214 | IF (Z%(A%,0)AND15)=14 THEN A%=Z%(A%,1): GOTO DEREF_A | |
215 | RETURN | |
216 | ||
217 | REM DEREF_B(B%) -> B% | |
218 | DEREF_B: | |
219 | IF (Z%(B%,0)AND15)=14 THEN B%=Z%(B%,1): GOTO DEREF_B | |
220 | RETURN | |
221 | ||
222 | CHECK_FREE_LIST: | |
223 | P1%=ZK%: P2%=0: REM start and accumulator | |
224 | CHECK_FREE_LIST_LOOP: | |
225 | IF P1%>=ZI% THEN GOTO CHECK_FREE_LIST_DONE | |
226 | IF (Z%(P1%,0)AND15)<>15 THEN P2%=-1: GOTO CHECK_FREE_LIST_DONE | |
227 | P2%=P2%+(Z%(P1%,0)AND-16)/16 | |
228 | P1%=Z%(P1%,1) | |
229 | GOTO CHECK_FREE_LIST_LOOP | |
230 | CHECK_FREE_LIST_DONE: | |
231 | IF P2%=-1 THEN PRINT "corrupt free list at "+STR$(P1%) | |
232 | RETURN | |
241d5d57 JM |
233 | |
234 | PR_MEMORY_SUMMARY: | |
4b84a23b | 235 | GOSUB CHECK_FREE_LIST: REM get count in P2% |
241d5d57 JM |
236 | |
237 | PRINT "Free memory (FRE) : " + STR$(FRE(0)) | |
4b84a23b JM |
238 | PRINT "Value memory (Z%) : " + STR$(ZI%-1) + " /" + STR$(S1%) |
239 | PRINT " "; | |
240 | PRINT " used:"+STR$(ZI%-1-P2%)+", freed:"+STR$(P2%); | |
241 | PRINT ", post repl_env:"+STR$(ZT%) | |
241d5d57 | 242 | PRINT "String values (ZS$) : " + STR$(ZJ%) + " /" + STR$(S2%) |
60270667 | 243 | PRINT "Call stack size (ZZ%) : " + STR$(ZL%+1) + " /" + STR$(S3%) |
241d5d57 JM |
244 | RETURN |
245 | ||
4b84a23b | 246 | REM PR_MEMORY(P1%, P2%) -> nil |
241d5d57 | 247 | PR_MEMORY: |
4b84a23b JM |
248 | IF P2%<P1% THEN P2%=ZI%-1 |
249 | PRINT "vvvvvv" | |
250 | PRINT "Z% Value Memory"+STR$(P1%)+"->"+STR$(P2%); | |
251 | PRINT " (ZI%: "+STR$(ZI%)+", ZK%: "+STR$(ZK%)+"):" | |
252 | IF P2%<P1% THEN PRINT " ---": GOTO PR_MEMORY_AFTER_VALUES | |
253 | I=P1% | |
254 | PR_MEMORY_VALUE_LOOP: | |
255 | IF I>P2% THEN GOTO PR_MEMORY_AFTER_VALUES | |
256 | PRINT " " + STR$(I); | |
257 | IF (Z%(I,0)AND15)=15 THEN GOTO PR_MEMORY_FREE | |
258 | PRINT ": ref cnt: " + STR$((Z%(I,0)AND-16)/16); | |
259 | PRINT ", type: " + STR$(Z%(I,0)AND15) + ", value: " + STR$(Z%(I,1)) | |
260 | I=I+1 | |
412e7348 JM |
261 | IF (Z%(I-1,0)AND15)<>10 THEN GOTO PR_MEMORY_VALUE_LOOP |
262 | PRINT " "+STR$(I)+": "; | |
263 | PRINT "params: "+STR$(Z%(I+1,0))+", env:"+STR$(Z%(I+1,1)) | |
264 | I=I+1 | |
4b84a23b JM |
265 | GOTO PR_MEMORY_VALUE_LOOP |
266 | PR_MEMORY_FREE: | |
267 | PRINT ": FREE size: "+STR$((Z%(I,0)AND-16)/16)+", next: "+STR$(Z%(I,1)); | |
268 | IF I=ZK% THEN PRINT " (free list start)"; | |
269 | ||
412e7348 | 270 | IF (Z%(I,0)AND-16)=32 THEN I=I+1: PRINT " "+STR$(I)+": ---" |
4b84a23b JM |
271 | I=I+1 |
272 | GOTO PR_MEMORY_VALUE_LOOP | |
273 | PR_MEMORY_AFTER_VALUES: | |
274 | PRINT "ZS% String Memory (ZJ%: " + STR$(ZJ%) + "):" | |
275 | IF ZJ%<=0 THEN PRINT " ---": GOTO PR_MEMORY_SKIP_STRINGS | |
241d5d57 JM |
276 | FOR I=0 TO ZJ%-1 |
277 | PRINT " " + STR$(I) + ": '" + ZS$(I) + "'" | |
278 | NEXT I | |
4b84a23b JM |
279 | PR_MEMORY_SKIP_STRINGS: |
280 | PRINT "ZZ% Stack Memory (ZL%: " + STR$(ZL%) + "):" | |
281 | IF ZL%<0 THEN PRINT " ---": GOTO PR_MEMORY_SKIP_STACK | |
282 | FOR I=0 TO ZL% | |
283 | PRINT " "+STR$(I)+": "+STR$(ZZ%(I)) | |
284 | NEXT I | |
285 | PR_MEMORY_SKIP_STACK: | |
286 | PRINT "^^^^^^" | |
241d5d57 JM |
287 | RETURN |
288 | ||
4b84a23b JM |
289 | |
290 | REM general functions | |
b7b1787f | 291 | |
241d5d57 JM |
292 | REM EQUAL_Q(A%, B%) -> R% |
293 | EQUAL_Q: | |
4b84a23b JM |
294 | GOSUB DEREF_A: GOSUB DEREF_B |
295 | ||
241d5d57 | 296 | R%=0 |
4b84a23b | 297 | U1%=(Z%(A%,0)AND15): U2%=(Z%(B%,0)AND15) |
60270667 | 298 | IF NOT ((U1%=U2%) OR ((U1%=6 OR U1%=7) AND (U2%=6 OR U2%=7))) THEN RETURN |
241d5d57 | 299 | IF U1%=6 THEN GOTO EQUAL_Q_SEQ |
60270667 JM |
300 | IF U1%=7 THEN GOTO EQUAL_Q_SEQ |
301 | IF U1%=8 THEN GOTO EQUAL_Q_HM | |
241d5d57 JM |
302 | |
303 | IF Z%(A%,1)=Z%(B%,1) THEN R%=1 | |
304 | RETURN | |
305 | ||
306 | EQUAL_Q_SEQ: | |
4b84a23b JM |
307 | IF (Z%(A%,1)=0) AND (Z%(B%,1)=0) THEN R%=1: RETURN |
308 | IF (Z%(A%,1)=0) OR (Z%(B%,1)=0) THEN R%=0: RETURN | |
309 | ||
310 | REM push A% and B% | |
311 | ZL%=ZL%+2: ZZ%(ZL%-1)=A%: ZZ%(ZL%)=B% | |
312 | A%=Z%(A%+1,1): B%=Z%(B%+1,1): GOSUB EQUAL_Q | |
313 | REM pop A% and B% | |
314 | A%=ZZ%(ZL%-1): B%=ZZ%(ZL%): ZL%=ZL%-2 | |
315 | IF R%=0 THEN RETURN | |
316 | ||
317 | REM next elements of the sequences | |
318 | A%=Z%(A%,1): B%=Z%(B%,1): GOTO EQUAL_Q_SEQ | |
241d5d57 JM |
319 | EQUAL_Q_HM: |
320 | R%=0 | |
321 | RETURN | |
322 | ||
323 | REM string functions | |
b7b1787f | 324 | |
241d5d57 JM |
325 | REM STRING_(AS$) -> R% |
326 | REM intern string (returns string index, not Z% index) | |
327 | STRING: | |
328 | IF ZJ%=0 THEN GOTO STRING_NOT_FOUND | |
b7b1787f | 329 | |
241d5d57 JM |
330 | REM search for matching string in ZS$ |
331 | FOR I=0 TO ZJ%-1 | |
332 | IF AS$=ZS$(I) THEN R%=I: RETURN | |
333 | NEXT I | |
334 | ||
335 | STRING_NOT_FOUND: | |
336 | ZS$(ZJ%) = AS$ | |
337 | R%=ZJ% | |
338 | ZJ%=ZJ%+1 | |
339 | RETURN | |
340 | ||
341 | ||
342 | ||
343 | ||
344 | REM list functions | |
345 | ||
346 | REM LIST_Q(A%) -> R% | |
b7b1787f JM |
347 | LIST_Q: |
348 | R%=0 | |
4b84a23b | 349 | IF (Z%(A%,0)AND15)=6 THEN R%=1 |
b7b1787f JM |
350 | RETURN |
351 | ||
4b84a23b | 352 | REM EMPTY_Q(A%) -> R% |
b7b1787f JM |
353 | EMPTY_Q: |
354 | R%=0 | |
355 | IF Z%(A%,1)=0 THEN R%=1 | |
356 | RETURN | |
357 | ||
4b84a23b JM |
358 | REM COUNT(A%) -> R% |
359 | COUNT: | |
360 | R%=-1 | |
361 | DO_COUNT_LOOP: | |
362 | R%=R%+1 | |
363 | IF Z%(A%,1)<>0 THEN A%=Z%(A%,1): GOTO DO_COUNT_LOOP | |
364 | RETURN | |
365 | ||
241d5d57 JM |
366 | REM LAST(A%) -> R% |
367 | LAST: | |
368 | REM TODO check that actually a list/vector | |
369 | IF Z%(A%,1)=0 THEN R%=0: RETURN: REM empty seq, return nil | |
370 | T6%=0 | |
371 | LAST_LOOP: | |
4b84a23b | 372 | IF Z%(A%,1)=0 THEN GOTO LAST_DONE: REM end, return previous value |
241d5d57 JM |
373 | T6%=A%: REM current becomes previous entry |
374 | A%=Z%(A%,1): REM next entry | |
375 | GOTO LAST_LOOP | |
4b84a23b JM |
376 | LAST_DONE: |
377 | R%=T6%+1: GOSUB DEREF_R | |
378 | Z%(R%,0)=Z%(R%,0)+16 | |
379 | RETURN | |
241d5d57 JM |
380 | |
381 | REM hashmap functions | |
b7b1787f JM |
382 | |
383 | REM HASHMAP() -> R% | |
384 | HASHMAP: | |
4b84a23b JM |
385 | SZ%=2: GOSUB ALLOC |
386 | Z%(R%,0) = 8+16 | |
387 | Z%(R%,1) = 0 | |
388 | Z%(R%+1,0) = 14 | |
389 | Z%(R%+1,1) = 0 | |
b7b1787f JM |
390 | RETURN |
391 | ||
392 | REM ASSOC1(HM%, K%, V%) -> R% | |
393 | ASSOC1: | |
4b84a23b JM |
394 | REM deref to actual key and value |
395 | R%=K%: GOSUB DEREF_R: K%=R% | |
396 | R%=V%: GOSUB DEREF_R: V%=R% | |
397 | ||
398 | REM inc ref count of key and value | |
399 | Z%(K%,0)=Z%(K%,0)+16 | |
400 | Z%(V%,0)=Z%(V%,0)+16 | |
401 | SZ%=4: GOSUB ALLOC | |
b7b1787f | 402 | REM key ptr |
4b84a23b JM |
403 | Z%(R%,0) = 8+16 |
404 | Z%(R%,1) = R%+2: REM point to next element (value) | |
405 | Z%(R%+1,0) = 14 | |
406 | Z%(R%+1,1) = K% | |
b7b1787f | 407 | REM value ptr |
4b84a23b JM |
408 | Z%(R%+2,0) = 8+16 |
409 | Z%(R%+2,1) = HM%: REM hashmap to assoc onto | |
410 | Z%(R%+3,0) = 14 | |
411 | Z%(R%+3,1) = V% | |
b7b1787f JM |
412 | RETURN |
413 | ||
414 | REM ASSOC1(HM%, K$, V%) -> R% | |
415 | ASSOC1_S: | |
416 | REM add the key string, then call ASSOC1 | |
4b84a23b JM |
417 | SZ%=1: GOSUB ALLOC |
418 | K%=R% | |
b7b1787f | 419 | ZS$(ZJ%) = K$ |
4b84a23b JM |
420 | Z%(R%,0) = 4: REM key ref cnt will be inc'd by ASSOC1 |
421 | Z%(R%,1) = ZJ% | |
b7b1787f JM |
422 | ZJ%=ZJ%+1 |
423 | GOSUB ASSOC1 | |
424 | RETURN | |
425 | ||
426 | REM HASHMAP_GET(HM%, K%) -> R% | |
427 | HASHMAP_GET: | |
428 | H2%=HM% | |
429 | T1$=ZS$(Z%(K%,1)): REM search key string | |
430 | T3%=0: REM whether found or not (for HASHMAP_CONTAINS) | |
431 | R%=0 | |
432 | HASHMAP_GET_LOOP: | |
433 | REM no matching key found | |
434 | IF Z%(H2%,1)=0 THEN R%=0: RETURN | |
435 | REM follow value ptrs | |
436 | T2%=H2%+1 | |
437 | HASHMAP_GET_DEREF: | |
4b84a23b | 438 | IF Z%(T2%,0)=14 THEN T2%=Z%(T2%,1): GOTO HASHMAP_GET_DEREF |
b7b1787f JM |
439 | REM get key string |
440 | T2$=ZS$(Z%(T2%,1)) | |
441 | REM if they are equal, we found it | |
442 | IF T1$=T2$ THEN T3%=1: R%=Z%(H2%,1)+1: RETURN | |
443 | REM skip to next key | |
444 | H2%=Z%(Z%(H2%,1),1) | |
445 | GOTO HASHMAP_GET_LOOP | |
446 | ||
447 | REM HASHMAP_CONTAINS(HM%, K%) -> R% | |
448 | HASHMAP_CONTAINS: | |
449 | GOSUB HASHMAP_GET | |
0cb556e0 | 450 | R%=T3% |
b7b1787f JM |
451 | RETURN |
452 | ||
453 | REM NATIVE_FUNCTION(A%) -> R% | |
454 | NATIVE_FUNCTION: | |
4b84a23b JM |
455 | SZ%=1: GOSUB ALLOC |
456 | Z%(R%,0) = 9+16 | |
457 | Z%(R%,1) = A% | |
b7b1787f | 458 | RETURN |
11f94d2e | 459 | |
241d5d57 | 460 | REM NATIVE_FUNCTION(A%, P%, E%) -> R% |
b7b1787f | 461 | MAL_FUNCTION: |
4b84a23b JM |
462 | SZ%=2: GOSUB ALLOC |
463 | Z%(A%,0)=Z%(A%,0)+16 | |
464 | Z%(P%,0)=Z%(P%,0)+16 | |
465 | Z%(E%,0)=Z%(E%,0)+16 | |
466 | ||
467 | Z%(R%,0) = 10+16 | |
468 | Z%(R%,1) = A% | |
469 | Z%(R%+1,0) = P% | |
470 | Z%(R%+1,1) = E% | |
11f94d2e | 471 | RETURN |