blob: bc9689ecd0bc1a5b09413faef58cc7d1f1c1f201 [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
13 CALL WORD_MATCHES
14 POP DI
15 POP BX
16
17 TEST AX, AX
18 JNZ .MATCH
19
20 MOV BX, WORD [BX] ; Offset 0 = *LINK
21 TEST BX, BX
22 JNZ .LOOP ; If BX is 0 (end) fall through
swissChili7c626b92022-01-01 23:35:39 -080023
swissChilif7f1e2b2021-12-31 14:42:43 -080024.MATCH:
25 PUSH BX ; BX holds dict entry
26 NEXT
27
28
swissChilice85f572022-04-20 16:54:34 -070029 ;; BX - Word entry on dictionary
swissChilif7f1e2b2021-12-31 14:42:43 -080030 ;; CX - Length
swissChilice85f572022-04-20 16:54:34 -070031 ;; DI - Name to compare to
swissChilif7f1e2b2021-12-31 14:42:43 -080032 ;;
33 ;; All three parameter registers may be clobbered.
34 ;;
35 ;; Return: AX - 0 or 1
36WORD_MATCHES:
37 MOV AL, BYTE [BX + WORDSZ] ; Word length
38 AND AL, LENGTH_MASK | HIDDEN_BIT
39 CMP AL, CL
40
41 JE .EQUAL
42
43 XOR AX, AX
44 RET
45
46.EQUAL:
47 PUSH SI
48 LEA SI, [BX + 3] ; Point to the dict entry name
49
50.LOOP:
51 CMPSB
52 JNE .END
53 LOOP .LOOP
54
55 MOV AX, 1
56 POP SI
57 RET
58
59.END:
60 XOR AX, AX
61 POP SI
62 RET
63
64
65 ;; ( *addr -- value )
66 DEFWORD_RAW GET, '@'
67 POP BX
68 PUSH WORD [BX]
69 NEXT
70
71
72 ;; ( value *addr -- )
73 DEFWORD_RAW SET, '!'
74 POP BX
75 POP AX
76 MOV WORD [BX], AX
77 NEXT
78
79
80 DEFWORD_RAW GETCHAR, 'C@'
81 POP BX
82 XOR AX, AX
83 MOV AL, BYTE [BX]
84 PUSH AX
85 NEXT
86
87
swissChili94f1e762022-01-29 21:55:45 -080088 ;; ( char address -- )
89 DEFWORD_RAW SETCHAR, 'C!'
90 POP BX
91 POP AX
92 MOV BYTE [BX], AL
93 NEXT
94
95
swissChilif7f1e2b2021-12-31 14:42:43 -080096 ;; Code field address
97 DEFWORD_RAW CFA, '>CFA'
98 POP BX
99 ADD BX, 2
100
101 XOR CH, CH
102 MOV CL, BYTE [BX] ; String length
103 AND CL, LENGTH_MASK
104 ADD BX, CX ; Code field address
105 ADD BX, 2 ; 1 to round up, 1 to skip length
106 AND BX, (~1) ; Zero the last bit
107
swissChilif7f1e2b2021-12-31 14:42:43 -0800108 PUSH BX
109 NEXT
110
111
112 DEFWORD_THREADED DFA, '>DFA'
113 DW CFA, ADD2, EXIT
114
115
swissChilif8849dc2021-12-31 23:15:57 -0800116 ;; ( *a *b num -- )
117 ;; Copy NUM bytes from A to B
118 DEFWORD_RAW CMOVE, 'CMOVE'
119 RSPUSH SI
120 POP CX
121 POP DI
122 POP SI
123 REP MOVSB
124 RSPOP SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800125 NEXT
126
swissChilif7f1e2b2021-12-31 14:42:43 -0800127
swissChilif8849dc2021-12-31 23:15:57 -0800128 ;; ( a -- b )
129 ;; Round up to even number
130 DEFWORD_RAW ROUND_EVEN, 'ROUND-EVEN'
131 POP AX
132 INC AX
133 AND AX, (~1)
134 PUSH AX
135 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800136
swissChilif7f1e2b2021-12-31 14:42:43 -0800137
swissChili94f1e762022-01-29 21:55:45 -0800138 ;; ( start length -- )
swissChilif8849dc2021-12-31 23:15:57 -0800139 DEFWORD_RAW CMOVE_HERE, 'CMOVE,'
140 POP CX
141 RSPUSH SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800142 POP SI
swissChilif8849dc2021-12-31 23:15:57 -0800143 MOV DI, [VAR_HERE]
144 REP MOVSB
145 MOV [VAR_HERE], DI
146 RSPOP SI
147 NEXT
148
149
150 DEFWORD_THREADED CREATE, 'CREATE'
151 DW HERE, GET ; ( *here )
152 DW _WORD ; ( *here *string length )
swissChilif8849dc2021-12-31 23:15:57 -0800153 DW LATEST, GET ; ( *here *string length link )
154 DW COMMA, DUP, CHAR_COMMA ; ( *here *string length )
155 DW CMOVE_HERE ; ( *here )
156 DW HERE, GET ; ( *here *here[new] )
157 DW ROUND_EVEN ; ( here[new,even] )
158 DW HERE, SET ; ( *here )
159 DW LATEST, SET ; ( )
160 DW EXIT
swissChilif7f1e2b2021-12-31 14:42:43 -0800161
162
163 DEFWORD_RAW COMMA, ','
164 POP AX
165 MOV DI, [VAR_HERE]
166 STOSW
167 MOV [VAR_HERE], DI
168 NEXT
169
170
swissChilif8849dc2021-12-31 23:15:57 -0800171 DEFWORD_RAW CHAR_COMMA, 'C,'
172 POP AX
173 MOV DI, [VAR_HERE]
174 STOSB
175 MOV [VAR_HERE], DI
176 NEXT
177
178
swissChilif7f1e2b2021-12-31 14:42:43 -0800179 ;; Switch to interpret mode
180 DEFWORD_RAW_IMMEDIATE LEFTBRACKET, '['
181 MOV WORD [VAR_STATE], 0
182 NEXT
183
184
swissChilif8849dc2021-12-31 23:15:57 -0800185 DEFWORD_RAW RIGHTBRACKET, ']'
swissChilif7f1e2b2021-12-31 14:42:43 -0800186 MOV WORD [VAR_STATE], 1
187 NEXT
188
189
swissChilice85f572022-04-20 16:54:34 -0700190 DEFWORD_RAW_IMMEDIATE IMMEDIATE, 'IMMED'
swissChilif7f1e2b2021-12-31 14:42:43 -0800191 MOV BX, [VAR_LATEST]
192 XOR BYTE [BX + 2], IMMEDIATE_BIT
193 NEXT
194
195
196 ;; LATEST HIDDEN
197 DEFWORD_RAW HIDDEN, 'HIDDEN'
198 POP BX
199 XOR BYTE [BX + 2], HIDDEN_BIT
200 NEXT
201
202
203 ;; HIDE DUP
204 DEFWORD_THREADED HIDE, 'HIDE'
205 DW _WORD, FIND, HIDDEN, EXIT
206
207
208 DEFWORD_THREADED_IMMED TICK, "'"
209 DW _WORD, FIND, CFA, EXIT
210
211
212 DEFWORD_RAW BRANCH, 'BRANCH'
213 LODSW
214 ADD SI, AX
215 NEXT
216
217
218 DEFWORD_RAW ZEROBRANCH, '0BRANCH'
219 POP DX
220 LODSW
221 TEST DX, DX
222 JNZ .NOTZERO
223 ADD SI, AX
224
225.NOTZERO:
226 NEXT
227
228
229 DEFWORD_RAW LITSTRING, 'LITSTRING'
230 LODSW ; Length
231 PUSH SI
232 ADD SI, AX
233 INC SI ; Round up
234 AND SI, (~1)
235 PUSH AX
236 NEXT
237
238
swissChilif8849dc2021-12-31 23:15:57 -0800239 ;; ( entry -- type )
240 ;; 0 = immediate; 1 = normal
241 DEFWORD_THREADED GET_WORD_TYPE, 'WORD-TYPE'
242 DW LITERAL, 2, PLUS ; ( entry+2 )
243 DW GETCHAR ; ( length/flags )
244 DW LITERAL, IMMEDIATE_BIT ; ( length/flags IMMEDIATE_BIT )
245 DW AND ; ( 1=immediate;0=normal )
246 DW LITERAL, IMMEDIATE_BIT
247 DW XOR ; Toggle the bit
248 DW EXIT
249
250
swissChilif7f1e2b2021-12-31 14:42:43 -0800251 DEFWORD_THREADED INTERPRET, 'INTERPRET'
252 DW _WORD ; ( addr len )
253 DW _2DUP, FIND ; ( addr len entry? )
254 DW DUP ; ( addr len entry? entry? )
swissChilif8849dc2021-12-31 23:15:57 -0800255 DW ZEROBRANCH ; ( addr len entry? )
256 RELATIVE_ADDRESS .NUM ; FIND returned 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800257
swissChilif8849dc2021-12-31 23:15:57 -0800258 DW SWAP, DROP, SWAP, DROP ; ( entry )
259 DW DUP, CFA ; ( entry cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800260
swissChilif8849dc2021-12-31 23:15:57 -0800261 DW SWAP ; ( cfa entry )
262 DW GET_WORD_TYPE ; ( cfa immediate? )
swissChilif7f1e2b2021-12-31 14:42:43 -0800263
swissChilif8849dc2021-12-31 23:15:57 -0800264 DW STATE, GET ; ( cfa immediate? interpreting? )
265 ;; In either case evaluate
266 DW ZEROBRANCH ; ( cfa immediate? )
swissChilice85f572022-04-20 16:54:34 -0700267 ;; We are currently interpreting:
swissChilif8849dc2021-12-31 23:15:57 -0800268 RELATIVE_ADDRESS .WORD_IMMED
269 DW ZEROBRANCH ; ( cfa )
270 RELATIVE_ADDRESS .WORD_COMPILE_IMMED
271
272 ;; Compile the word
swissChilif7f1e2b2021-12-31 14:42:43 -0800273 DW COMMA ; Add to HERE
274 DW EXIT
275
swissChilif8849dc2021-12-31 23:15:57 -0800276.WORD_IMMED: ; ( cfa immediate? )
277 DW DROP ; ( cfa )
swissChilice85f572022-04-20 16:54:34 -0700278.WORD_COMPILE_IMMED: ; ( cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800279 DW EXECUTE ; ( )
280 DW EXIT
281
282.NUM: ; ( addr len 0 )
283 DW DROP ; ( addr len )
swissChilice85f572022-04-20 16:54:34 -0700284 INCLUDE_STRING 'Parsing as a number'
285 DW TYPE, CR
286 DW _2DUP, TYPE, CR
swissChilif7f1e2b2021-12-31 14:42:43 -0800287 DW NUMBER ; ( number unparsed )
swissChilif8849dc2021-12-31 23:15:57 -0800288 DW ZEROBRANCH ; ( number )
289 RELATIVE_ADDRESS .NUMOK
swissChilif7f1e2b2021-12-31 14:42:43 -0800290
swissChilif8849dc2021-12-31 23:15:57 -0800291 INCLUDE_STRING 'Word is neither defined nor a number'
292 DW TYPE, CR ; ( number )
293 DW DROP, EXIT ; ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800294
295.NUMOK:
296 ;; ( number )
297 DW STATE, GET ; ( number STATE )
swissChilif8849dc2021-12-31 23:15:57 -0800298 DW ZEROBRANCH ; ( number )
299 RELATIVE_ADDRESS .NUM_IMMED
swissChilif7f1e2b2021-12-31 14:42:43 -0800300
301 DW LITERAL, LITERAL ; ( number LITERAL )
302 DW COMMA, COMMA ; ( )
303
swissChilif8849dc2021-12-31 23:15:57 -0800304.NUM_IMMED: ; ( number ) or ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800305 DW EXIT
306
swissChilif7f1e2b2021-12-31 14:42:43 -0800307
swissChilif8849dc2021-12-31 23:15:57 -0800308 ;; Jump to the word specified by the CFA on the stack
swissChilif7f1e2b2021-12-31 14:42:43 -0800309 DEFWORD_RAW EXECUTE, 'EXECUTE'
310 POP AX
311 MOV BX, AX
312 JMP [BX]
313
314
315 ;; TODO: await newline
316 DEFWORD_THREADED QUIT, 'QUIT'
swissChilif8849dc2021-12-31 23:15:57 -0800317.START:
swissChilif7f1e2b2021-12-31 14:42:43 -0800318 DW INTERPRET
swissChilif8849dc2021-12-31 23:15:57 -0800319 DW BRANCH
320 RELATIVE_ADDRESS .START
swissChilif7f1e2b2021-12-31 14:42:43 -0800321
322
323 DEFWORD_THREADED COLON, ':'
swissChilif8849dc2021-12-31 23:15:57 -0800324 DW CREATE
swissChilif7f1e2b2021-12-31 14:42:43 -0800325 DW LITERAL, DOCOL, COMMA
326 DW LATEST, GET, HIDDEN
327 DW RIGHTBRACKET
328 DW EXIT
329
330
331 DEFWORD_THREADED_IMMED SEMICOLON, ';'
332 DW LITERAL, EXIT, COMMA
333 DW LATEST, GET, HIDDEN
334 DW LEFTBRACKET
335 DW EXIT
336
337
338 ;; ( *entry -- len *string )
swissChilif8849dc2021-12-31 23:15:57 -0800339 DEFWORD_THREADED ENTRY_NAME, 'ENTRY->NAME'
swissChilif7f1e2b2021-12-31 14:42:43 -0800340 DW DUP ; ( *entry *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800341 DW LITERAL, 2, PLUS ; ( *entry *len/flags )
342 DW GETCHAR ; ( *entry len/flags )
343 DW LITERAL, LENGTH_MASK, AND ; ( *entry len )
swissChilif7f1e2b2021-12-31 14:42:43 -0800344 DW SWAP ; ( len *entry )
345 DW LITERAL, 3, PLUS ; ( len *string )
346 DW SWAP
347 DW EXIT
348
349
swissChilif8849dc2021-12-31 23:15:57 -0800350 DEFWORD_THREADED SHOW_DICT, 'WORDS'
swissChilif7f1e2b2021-12-31 14:42:43 -0800351 DW LATEST, GET ; ( *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800352.LOOP:
swissChilif7f1e2b2021-12-31 14:42:43 -0800353 DW DUP, ENTRY_NAME ; ( *entry len *string)
swissChilif8849dc2021-12-31 23:15:57 -0800354 DW TYPE, SPACE ; ( *entry )
swissChilif7f1e2b2021-12-31 14:42:43 -0800355 DW GET ; ( *prev-entry )
356 DW DUP ; ( *prev-entry *prev-entry )
swissChilif8849dc2021-12-31 23:15:57 -0800357 DW ZEROBRANCH
358 RELATIVE_ADDRESS .DONE
359
360 DW BRANCH ; Back to start!
361 RELATIVE_ADDRESS .LOOP
362.DONE:
363 DW CR, EXIT
swissChili7c626b92022-01-01 23:35:39 -0800364
365
366 DEFWORD_RAW SHOW_STACK, '.S'
367 MOV CX, WORD [CONST_SP_INITIAL]
368 RSPUSH SI
369 STD ; Go backwards
370
371 MOV SI, CX ; Going down
372 SUB SI, 2 ; Just below it
373 SUB CX, SP ; Number of bytes on the stack
374 JLE .DONE ; Below stack bottom (oops!)
375 SHR CX, 1 ; Divide by 2 -- number of cells
376
377.LOOP:
378 LODSW
379 PUSH CX ; Clobbered
380 CALL DOT_INT
381 POP CX
382
383 MOV DX, ' '
384 WRITECOUT
385
386 LOOP .LOOP
387
388.DONE:
389 MOV DX, CRLF_MSG
390 WRITESOUT
391
392 RSPOP SI
393 CLD
394 NEXT
395
396
397 DEFWORD_THREADED DUMP_IMAGE, 'DUMP-IMAGE'
398 DW LITERAL, F_WRITE ; ( *string len flags )
399 DW OPEN_FILE ; ( handle )
400 DW DUP ; ( handle handle )
401 DW LITERAL, 100h ; ( handle handle *start )
402 DW SWAP, HERE, GET ; ( handle *start handle *here )
403 DW SWAP, FILE_WRITE_RANGE ; ( handle )
404 DW CLOSE_FILE ; ( )
405 DW EXIT