blob: 08a5dbf1e12f1f6f2bc5db7a3d34ed261e654b20 [file] [log] [blame]
swissChilif7f1e2b2021-12-31 14:42:43 -08001;;; Dictionary manipulation & memory management words
swissChili7c626b92022-01-01 23:35:39 -08002
swissChilif7f1e2b2021-12-31 14:42:43 -08003 ;; ( addr len -- entry? )
4 DEFWORD_RAW FIND, 'FIND'
5 POP CX ; String length
6 POP DI ; Start pointer
7 MOV BX, WORD [VAR_LATEST]
8
9.LOOP:
10 ;; BX and DI are clobbered
11 PUSH BX
12 PUSH DI
swissChilib921e822022-04-20 19:47:33 -070013 PUSH CX
swissChilif7f1e2b2021-12-31 14:42:43 -080014 CALL WORD_MATCHES
swissChilib921e822022-04-20 19:47:33 -070015 POP CX
swissChilif7f1e2b2021-12-31 14:42:43 -080016 POP DI
17 POP BX
18
19 TEST AX, AX
20 JNZ .MATCH
21
22 MOV BX, WORD [BX] ; Offset 0 = *LINK
23 TEST BX, BX
24 JNZ .LOOP ; If BX is 0 (end) fall through
swissChili7c626b92022-01-01 23:35:39 -080025
swissChilif7f1e2b2021-12-31 14:42:43 -080026.MATCH:
27 PUSH BX ; BX holds dict entry
28 NEXT
29
30
swissChilice85f572022-04-20 16:54:34 -070031 ;; BX - Word entry on dictionary
swissChilif7f1e2b2021-12-31 14:42:43 -080032 ;; CX - Length
swissChilice85f572022-04-20 16:54:34 -070033 ;; DI - Name to compare to
swissChilif7f1e2b2021-12-31 14:42:43 -080034 ;;
35 ;; All three parameter registers may be clobbered.
36 ;;
37 ;; Return: AX - 0 or 1
38WORD_MATCHES:
39 MOV AL, BYTE [BX + WORDSZ] ; Word length
40 AND AL, LENGTH_MASK | HIDDEN_BIT
41 CMP AL, CL
42
43 JE .EQUAL
44
45 XOR AX, AX
46 RET
47
48.EQUAL:
49 PUSH SI
50 LEA SI, [BX + 3] ; Point to the dict entry name
51
52.LOOP:
53 CMPSB
54 JNE .END
55 LOOP .LOOP
56
57 MOV AX, 1
58 POP SI
59 RET
60
61.END:
62 XOR AX, AX
63 POP SI
64 RET
65
66
67 ;; ( *addr -- value )
68 DEFWORD_RAW GET, '@'
69 POP BX
70 PUSH WORD [BX]
71 NEXT
72
73
74 ;; ( value *addr -- )
75 DEFWORD_RAW SET, '!'
76 POP BX
77 POP AX
78 MOV WORD [BX], AX
79 NEXT
80
81
82 DEFWORD_RAW GETCHAR, 'C@'
83 POP BX
84 XOR AX, AX
85 MOV AL, BYTE [BX]
86 PUSH AX
87 NEXT
88
89
swissChili94f1e762022-01-29 21:55:45 -080090 ;; ( char address -- )
91 DEFWORD_RAW SETCHAR, 'C!'
92 POP BX
93 POP AX
94 MOV BYTE [BX], AL
95 NEXT
96
97
swissChilif7f1e2b2021-12-31 14:42:43 -080098 ;; Code field address
99 DEFWORD_RAW CFA, '>CFA'
100 POP BX
101 ADD BX, 2
102
103 XOR CH, CH
104 MOV CL, BYTE [BX] ; String length
105 AND CL, LENGTH_MASK
106 ADD BX, CX ; Code field address
107 ADD BX, 2 ; 1 to round up, 1 to skip length
108 AND BX, (~1) ; Zero the last bit
109
swissChilif7f1e2b2021-12-31 14:42:43 -0800110 PUSH BX
111 NEXT
112
113
114 DEFWORD_THREADED DFA, '>DFA'
115 DW CFA, ADD2, EXIT
116
117
swissChilif8849dc2021-12-31 23:15:57 -0800118 ;; ( *a *b num -- )
119 ;; Copy NUM bytes from A to B
120 DEFWORD_RAW CMOVE, 'CMOVE'
121 RSPUSH SI
122 POP CX
123 POP DI
124 POP SI
125 REP MOVSB
126 RSPOP SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800127 NEXT
128
swissChilif7f1e2b2021-12-31 14:42:43 -0800129
swissChilif8849dc2021-12-31 23:15:57 -0800130 ;; ( a -- b )
131 ;; Round up to even number
132 DEFWORD_RAW ROUND_EVEN, 'ROUND-EVEN'
133 POP AX
134 INC AX
135 AND AX, (~1)
136 PUSH AX
137 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800138
swissChilif7f1e2b2021-12-31 14:42:43 -0800139
swissChili94f1e762022-01-29 21:55:45 -0800140 ;; ( start length -- )
swissChilif8849dc2021-12-31 23:15:57 -0800141 DEFWORD_RAW CMOVE_HERE, 'CMOVE,'
142 POP CX
143 RSPUSH SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800144 POP SI
swissChilif8849dc2021-12-31 23:15:57 -0800145 MOV DI, [VAR_HERE]
146 REP MOVSB
147 MOV [VAR_HERE], DI
148 RSPOP SI
149 NEXT
150
151
152 DEFWORD_THREADED CREATE, 'CREATE'
153 DW HERE, GET ; ( *here )
154 DW _WORD ; ( *here *string length )
swissChilif8849dc2021-12-31 23:15:57 -0800155 DW LATEST, GET ; ( *here *string length link )
156 DW COMMA, DUP, CHAR_COMMA ; ( *here *string length )
157 DW CMOVE_HERE ; ( *here )
158 DW HERE, GET ; ( *here *here[new] )
159 DW ROUND_EVEN ; ( here[new,even] )
160 DW HERE, SET ; ( *here )
161 DW LATEST, SET ; ( )
162 DW EXIT
swissChilif7f1e2b2021-12-31 14:42:43 -0800163
164
165 DEFWORD_RAW COMMA, ','
166 POP AX
167 MOV DI, [VAR_HERE]
168 STOSW
169 MOV [VAR_HERE], DI
170 NEXT
171
172
swissChilif8849dc2021-12-31 23:15:57 -0800173 DEFWORD_RAW CHAR_COMMA, 'C,'
174 POP AX
175 MOV DI, [VAR_HERE]
176 STOSB
177 MOV [VAR_HERE], DI
178 NEXT
179
180
swissChilif7f1e2b2021-12-31 14:42:43 -0800181 ;; Switch to interpret mode
182 DEFWORD_RAW_IMMEDIATE LEFTBRACKET, '['
183 MOV WORD [VAR_STATE], 0
184 NEXT
185
186
swissChilif8849dc2021-12-31 23:15:57 -0800187 DEFWORD_RAW RIGHTBRACKET, ']'
swissChilif7f1e2b2021-12-31 14:42:43 -0800188 MOV WORD [VAR_STATE], 1
189 NEXT
190
191
swissChilib921e822022-04-20 19:47:33 -0700192 DEFWORD_RAW_IMMEDIATE IMMEDIATE, 'IMMEDIATE'
swissChilif7f1e2b2021-12-31 14:42:43 -0800193 MOV BX, [VAR_LATEST]
194 XOR BYTE [BX + 2], IMMEDIATE_BIT
195 NEXT
196
197
198 ;; LATEST HIDDEN
199 DEFWORD_RAW HIDDEN, 'HIDDEN'
200 POP BX
201 XOR BYTE [BX + 2], HIDDEN_BIT
202 NEXT
203
204
205 ;; HIDE DUP
206 DEFWORD_THREADED HIDE, 'HIDE'
207 DW _WORD, FIND, HIDDEN, EXIT
208
209
210 DEFWORD_THREADED_IMMED TICK, "'"
211 DW _WORD, FIND, CFA, EXIT
212
213
214 DEFWORD_RAW BRANCH, 'BRANCH'
215 LODSW
216 ADD SI, AX
217 NEXT
218
219
220 DEFWORD_RAW ZEROBRANCH, '0BRANCH'
221 POP DX
222 LODSW
223 TEST DX, DX
224 JNZ .NOTZERO
225 ADD SI, AX
226
227.NOTZERO:
228 NEXT
229
230
231 DEFWORD_RAW LITSTRING, 'LITSTRING'
232 LODSW ; Length
233 PUSH SI
234 ADD SI, AX
235 INC SI ; Round up
236 AND SI, (~1)
237 PUSH AX
238 NEXT
239
240
swissChilif8849dc2021-12-31 23:15:57 -0800241 ;; ( entry -- type )
242 ;; 0 = immediate; 1 = normal
243 DEFWORD_THREADED GET_WORD_TYPE, 'WORD-TYPE'
244 DW LITERAL, 2, PLUS ; ( entry+2 )
245 DW GETCHAR ; ( length/flags )
246 DW LITERAL, IMMEDIATE_BIT ; ( length/flags IMMEDIATE_BIT )
247 DW AND ; ( 1=immediate;0=normal )
248 DW LITERAL, IMMEDIATE_BIT
249 DW XOR ; Toggle the bit
250 DW EXIT
251
252
swissChilif7f1e2b2021-12-31 14:42:43 -0800253 DEFWORD_THREADED INTERPRET, 'INTERPRET'
254 DW _WORD ; ( addr len )
255 DW _2DUP, FIND ; ( addr len entry? )
256 DW DUP ; ( addr len entry? entry? )
swissChilif8849dc2021-12-31 23:15:57 -0800257 DW ZEROBRANCH ; ( addr len entry? )
258 RELATIVE_ADDRESS .NUM ; FIND returned 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800259
swissChilif8849dc2021-12-31 23:15:57 -0800260 DW SWAP, DROP, SWAP, DROP ; ( entry )
261 DW DUP, CFA ; ( entry cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800262
swissChilif8849dc2021-12-31 23:15:57 -0800263 DW SWAP ; ( cfa entry )
264 DW GET_WORD_TYPE ; ( cfa immediate? )
swissChilif7f1e2b2021-12-31 14:42:43 -0800265
swissChilif8849dc2021-12-31 23:15:57 -0800266 DW STATE, GET ; ( cfa immediate? interpreting? )
267 ;; In either case evaluate
268 DW ZEROBRANCH ; ( cfa immediate? )
swissChilice85f572022-04-20 16:54:34 -0700269 ;; We are currently interpreting:
swissChilif8849dc2021-12-31 23:15:57 -0800270 RELATIVE_ADDRESS .WORD_IMMED
271 DW ZEROBRANCH ; ( cfa )
272 RELATIVE_ADDRESS .WORD_COMPILE_IMMED
273
274 ;; Compile the word
swissChilif7f1e2b2021-12-31 14:42:43 -0800275 DW COMMA ; Add to HERE
276 DW EXIT
277
swissChilif8849dc2021-12-31 23:15:57 -0800278.WORD_IMMED: ; ( cfa immediate? )
279 DW DROP ; ( cfa )
swissChilice85f572022-04-20 16:54:34 -0700280.WORD_COMPILE_IMMED: ; ( cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800281 DW EXECUTE ; ( )
282 DW EXIT
283
284.NUM: ; ( addr len 0 )
285 DW DROP ; ( addr len )
286 DW NUMBER ; ( number unparsed )
swissChilif8849dc2021-12-31 23:15:57 -0800287 DW ZEROBRANCH ; ( number )
288 RELATIVE_ADDRESS .NUMOK
swissChilif7f1e2b2021-12-31 14:42:43 -0800289
swissChilif8849dc2021-12-31 23:15:57 -0800290 INCLUDE_STRING 'Word is neither defined nor a number'
291 DW TYPE, CR ; ( number )
292 DW DROP, EXIT ; ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800293
294.NUMOK:
295 ;; ( number )
296 DW STATE, GET ; ( number STATE )
swissChilif8849dc2021-12-31 23:15:57 -0800297 DW ZEROBRANCH ; ( number )
298 RELATIVE_ADDRESS .NUM_IMMED
swissChilif7f1e2b2021-12-31 14:42:43 -0800299
300 DW LITERAL, LITERAL ; ( number LITERAL )
301 DW COMMA, COMMA ; ( )
302
swissChilif8849dc2021-12-31 23:15:57 -0800303.NUM_IMMED: ; ( number ) or ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800304 DW EXIT
305
swissChilif7f1e2b2021-12-31 14:42:43 -0800306
swissChilif8849dc2021-12-31 23:15:57 -0800307 ;; Jump to the word specified by the CFA on the stack
swissChilif7f1e2b2021-12-31 14:42:43 -0800308 DEFWORD_RAW EXECUTE, 'EXECUTE'
309 POP AX
310 MOV BX, AX
311 JMP [BX]
312
313
314 ;; TODO: await newline
315 DEFWORD_THREADED QUIT, 'QUIT'
swissChilif8849dc2021-12-31 23:15:57 -0800316.START:
swissChilif7f1e2b2021-12-31 14:42:43 -0800317 DW INTERPRET
swissChilif8849dc2021-12-31 23:15:57 -0800318 DW BRANCH
319 RELATIVE_ADDRESS .START
swissChilif7f1e2b2021-12-31 14:42:43 -0800320
321
322 DEFWORD_THREADED COLON, ':'
swissChilif8849dc2021-12-31 23:15:57 -0800323 DW CREATE
swissChilif7f1e2b2021-12-31 14:42:43 -0800324 DW LITERAL, DOCOL, COMMA
325 DW LATEST, GET, HIDDEN
326 DW RIGHTBRACKET
327 DW EXIT
328
329
330 DEFWORD_THREADED_IMMED SEMICOLON, ';'
331 DW LITERAL, EXIT, COMMA
332 DW LATEST, GET, HIDDEN
333 DW LEFTBRACKET
334 DW EXIT
335
336
337 ;; ( *entry -- len *string )
swissChilif8849dc2021-12-31 23:15:57 -0800338 DEFWORD_THREADED ENTRY_NAME, 'ENTRY->NAME'
swissChilif7f1e2b2021-12-31 14:42:43 -0800339 DW DUP ; ( *entry *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800340 DW LITERAL, 2, PLUS ; ( *entry *len/flags )
341 DW GETCHAR ; ( *entry len/flags )
342 DW LITERAL, LENGTH_MASK, AND ; ( *entry len )
swissChilif7f1e2b2021-12-31 14:42:43 -0800343 DW SWAP ; ( len *entry )
344 DW LITERAL, 3, PLUS ; ( len *string )
345 DW SWAP
346 DW EXIT
347
348
swissChilif8849dc2021-12-31 23:15:57 -0800349 DEFWORD_THREADED SHOW_DICT, 'WORDS'
swissChilif7f1e2b2021-12-31 14:42:43 -0800350 DW LATEST, GET ; ( *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800351.LOOP:
swissChilif7f1e2b2021-12-31 14:42:43 -0800352 DW DUP, ENTRY_NAME ; ( *entry len *string)
swissChilif8849dc2021-12-31 23:15:57 -0800353 DW TYPE, SPACE ; ( *entry )
swissChilif7f1e2b2021-12-31 14:42:43 -0800354 DW GET ; ( *prev-entry )
355 DW DUP ; ( *prev-entry *prev-entry )
swissChilif8849dc2021-12-31 23:15:57 -0800356 DW ZEROBRANCH
357 RELATIVE_ADDRESS .DONE
358
359 DW BRANCH ; Back to start!
360 RELATIVE_ADDRESS .LOOP
361.DONE:
362 DW CR, EXIT
swissChili7c626b92022-01-01 23:35:39 -0800363
364
365 DEFWORD_RAW SHOW_STACK, '.S'
366 MOV CX, WORD [CONST_SP_INITIAL]
367 RSPUSH SI
368 STD ; Go backwards
369
370 MOV SI, CX ; Going down
371 SUB SI, 2 ; Just below it
372 SUB CX, SP ; Number of bytes on the stack
373 JLE .DONE ; Below stack bottom (oops!)
374 SHR CX, 1 ; Divide by 2 -- number of cells
375
376.LOOP:
377 LODSW
378 PUSH CX ; Clobbered
379 CALL DOT_INT
380 POP CX
381
382 MOV DX, ' '
383 WRITECOUT
384
385 LOOP .LOOP
386
387.DONE:
388 MOV DX, CRLF_MSG
389 WRITESOUT
390
391 RSPOP SI
392 CLD
393 NEXT
394
395
396 DEFWORD_THREADED DUMP_IMAGE, 'DUMP-IMAGE'
397 DW LITERAL, F_WRITE ; ( *string len flags )
398 DW OPEN_FILE ; ( handle )
399 DW DUP ; ( handle handle )
400 DW LITERAL, 100h ; ( handle handle *start )
401 DW SWAP, HERE, GET ; ( handle *start handle *here )
402 DW SWAP, FILE_WRITE_RANGE ; ( handle )
403 DW CLOSE_FILE ; ( )
404 DW EXIT