blob: 7a78fe8ced1702e292142017a13ba693772a88f3 [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
29 ;; BX - Word
30 ;; CX - Length
31 ;; DI - Name
32 ;;
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
108
109 PUSH BX
110 NEXT
111
112
113 DEFWORD_THREADED DFA, '>DFA'
114 DW CFA, ADD2, EXIT
115
116
swissChilif8849dc2021-12-31 23:15:57 -0800117 ;; ( *a *b num -- )
118 ;; Copy NUM bytes from A to B
119 DEFWORD_RAW CMOVE, 'CMOVE'
120 RSPUSH SI
121 POP CX
122 POP DI
123 POP SI
124 REP MOVSB
125 RSPOP SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800126 NEXT
127
swissChilif7f1e2b2021-12-31 14:42:43 -0800128
swissChilif8849dc2021-12-31 23:15:57 -0800129 ;; ( a -- b )
130 ;; Round up to even number
131 DEFWORD_RAW ROUND_EVEN, 'ROUND-EVEN'
132 POP AX
133 INC AX
134 AND AX, (~1)
135 PUSH AX
136 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800137
swissChilif7f1e2b2021-12-31 14:42:43 -0800138
swissChili94f1e762022-01-29 21:55:45 -0800139 ;; ( start length -- )
swissChilif8849dc2021-12-31 23:15:57 -0800140 DEFWORD_RAW CMOVE_HERE, 'CMOVE,'
141 POP CX
142 RSPUSH SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800143 POP SI
swissChilif8849dc2021-12-31 23:15:57 -0800144 MOV DI, [VAR_HERE]
145 REP MOVSB
146 MOV [VAR_HERE], DI
147 RSPOP SI
148 NEXT
149
150
151 DEFWORD_THREADED CREATE, 'CREATE'
152 DW HERE, GET ; ( *here )
153 DW _WORD ; ( *here *string length )
swissChilif8849dc2021-12-31 23:15:57 -0800154 DW LATEST, GET ; ( *here *string length link )
155 DW COMMA, DUP, CHAR_COMMA ; ( *here *string length )
156 DW CMOVE_HERE ; ( *here )
157 DW HERE, GET ; ( *here *here[new] )
158 DW ROUND_EVEN ; ( here[new,even] )
159 DW HERE, SET ; ( *here )
160 DW LATEST, SET ; ( )
161 DW EXIT
swissChilif7f1e2b2021-12-31 14:42:43 -0800162
163
164 DEFWORD_RAW COMMA, ','
165 POP AX
166 MOV DI, [VAR_HERE]
167 STOSW
168 MOV [VAR_HERE], DI
169 NEXT
170
171
swissChilif8849dc2021-12-31 23:15:57 -0800172 DEFWORD_RAW CHAR_COMMA, 'C,'
173 POP AX
174 MOV DI, [VAR_HERE]
175 STOSB
176 MOV [VAR_HERE], DI
177 NEXT
178
179
swissChilif7f1e2b2021-12-31 14:42:43 -0800180 ;; Switch to interpret mode
181 DEFWORD_RAW_IMMEDIATE LEFTBRACKET, '['
182 MOV WORD [VAR_STATE], 0
183 NEXT
184
185
swissChilif8849dc2021-12-31 23:15:57 -0800186 DEFWORD_RAW RIGHTBRACKET, ']'
swissChilif7f1e2b2021-12-31 14:42:43 -0800187 MOV WORD [VAR_STATE], 1
188 NEXT
189
190
swissChilif8849dc2021-12-31 23:15:57 -0800191 DEFWORD_RAW_IMMEDIATE IMMEDIATE, 'IMMEDIATE'
swissChilif7f1e2b2021-12-31 14:42:43 -0800192 MOV BX, [VAR_LATEST]
193 XOR BYTE [BX + 2], IMMEDIATE_BIT
194 NEXT
195
196
197 ;; LATEST HIDDEN
198 DEFWORD_RAW HIDDEN, 'HIDDEN'
199 POP BX
200 XOR BYTE [BX + 2], HIDDEN_BIT
201 NEXT
202
203
204 ;; HIDE DUP
205 DEFWORD_THREADED HIDE, 'HIDE'
206 DW _WORD, FIND, HIDDEN, EXIT
207
208
209 DEFWORD_THREADED_IMMED TICK, "'"
210 DW _WORD, FIND, CFA, EXIT
211
212
213 DEFWORD_RAW BRANCH, 'BRANCH'
214 LODSW
215 ADD SI, AX
216 NEXT
217
218
219 DEFWORD_RAW ZEROBRANCH, '0BRANCH'
220 POP DX
221 LODSW
222 TEST DX, DX
223 JNZ .NOTZERO
224 ADD SI, AX
225
226.NOTZERO:
227 NEXT
228
229
230 DEFWORD_RAW LITSTRING, 'LITSTRING'
231 LODSW ; Length
232 PUSH SI
233 ADD SI, AX
234 INC SI ; Round up
235 AND SI, (~1)
236 PUSH AX
237 NEXT
238
239
swissChilif8849dc2021-12-31 23:15:57 -0800240 ;; ( entry -- type )
241 ;; 0 = immediate; 1 = normal
242 DEFWORD_THREADED GET_WORD_TYPE, 'WORD-TYPE'
243 DW LITERAL, 2, PLUS ; ( entry+2 )
244 DW GETCHAR ; ( length/flags )
245 DW LITERAL, IMMEDIATE_BIT ; ( length/flags IMMEDIATE_BIT )
246 DW AND ; ( 1=immediate;0=normal )
247 DW LITERAL, IMMEDIATE_BIT
248 DW XOR ; Toggle the bit
249 DW EXIT
250
251
swissChilif7f1e2b2021-12-31 14:42:43 -0800252 DEFWORD_THREADED INTERPRET, 'INTERPRET'
253 DW _WORD ; ( addr len )
254 DW _2DUP, FIND ; ( addr len entry? )
255 DW DUP ; ( addr len entry? entry? )
swissChilif8849dc2021-12-31 23:15:57 -0800256 DW ZEROBRANCH ; ( addr len entry? )
257 RELATIVE_ADDRESS .NUM ; FIND returned 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800258
swissChilif8849dc2021-12-31 23:15:57 -0800259 DW SWAP, DROP, SWAP, DROP ; ( entry )
260 DW DUP, CFA ; ( entry cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800261
swissChilif8849dc2021-12-31 23:15:57 -0800262 DW SWAP ; ( cfa entry )
263 DW GET_WORD_TYPE ; ( cfa immediate? )
swissChilif7f1e2b2021-12-31 14:42:43 -0800264
swissChilif8849dc2021-12-31 23:15:57 -0800265 DW STATE, GET ; ( cfa immediate? interpreting? )
266 ;; In either case evaluate
267 DW ZEROBRANCH ; ( cfa immediate? )
268 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 )
swissChilie4d2e282022-01-04 22:22:27 -0800278.WORD_COMPILE_IMMED:
swissChilif7f1e2b2021-12-31 14:42:43 -0800279 DW EXECUTE ; ( )
280 DW EXIT
281
282.NUM: ; ( addr len 0 )
283 DW DROP ; ( addr len )
284 DW NUMBER ; ( number unparsed )
swissChilif8849dc2021-12-31 23:15:57 -0800285 DW ZEROBRANCH ; ( number )
286 RELATIVE_ADDRESS .NUMOK
swissChilif7f1e2b2021-12-31 14:42:43 -0800287
swissChilif8849dc2021-12-31 23:15:57 -0800288 INCLUDE_STRING 'Word is neither defined nor a number'
289 DW TYPE, CR ; ( number )
290 DW DROP, EXIT ; ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800291
292.NUMOK:
293 ;; ( number )
294 DW STATE, GET ; ( number STATE )
swissChilif8849dc2021-12-31 23:15:57 -0800295 DW ZEROBRANCH ; ( number )
296 RELATIVE_ADDRESS .NUM_IMMED
swissChilif7f1e2b2021-12-31 14:42:43 -0800297
298 DW LITERAL, LITERAL ; ( number LITERAL )
299 DW COMMA, COMMA ; ( )
300
swissChilif8849dc2021-12-31 23:15:57 -0800301.NUM_IMMED: ; ( number ) or ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800302 DW EXIT
303
swissChilif7f1e2b2021-12-31 14:42:43 -0800304
swissChilif8849dc2021-12-31 23:15:57 -0800305 ;; Jump to the word specified by the CFA on the stack
swissChilif7f1e2b2021-12-31 14:42:43 -0800306 DEFWORD_RAW EXECUTE, 'EXECUTE'
307 POP AX
308 MOV BX, AX
309 JMP [BX]
310
311
312 ;; TODO: await newline
313 DEFWORD_THREADED QUIT, 'QUIT'
swissChilif8849dc2021-12-31 23:15:57 -0800314.START:
swissChilif7f1e2b2021-12-31 14:42:43 -0800315 DW INTERPRET
swissChilif8849dc2021-12-31 23:15:57 -0800316 DW BRANCH
317 RELATIVE_ADDRESS .START
swissChilif7f1e2b2021-12-31 14:42:43 -0800318
319
320 DEFWORD_THREADED COLON, ':'
swissChilif8849dc2021-12-31 23:15:57 -0800321 DW CREATE
swissChilif7f1e2b2021-12-31 14:42:43 -0800322 DW LITERAL, DOCOL, COMMA
323 DW LATEST, GET, HIDDEN
324 DW RIGHTBRACKET
325 DW EXIT
326
327
328 DEFWORD_THREADED_IMMED SEMICOLON, ';'
329 DW LITERAL, EXIT, COMMA
330 DW LATEST, GET, HIDDEN
331 DW LEFTBRACKET
332 DW EXIT
333
334
335 ;; ( *entry -- len *string )
swissChilif8849dc2021-12-31 23:15:57 -0800336 DEFWORD_THREADED ENTRY_NAME, 'ENTRY->NAME'
swissChilif7f1e2b2021-12-31 14:42:43 -0800337 DW DUP ; ( *entry *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800338 DW LITERAL, 2, PLUS ; ( *entry *len/flags )
339 DW GETCHAR ; ( *entry len/flags )
340 DW LITERAL, LENGTH_MASK, AND ; ( *entry len )
swissChilif7f1e2b2021-12-31 14:42:43 -0800341 DW SWAP ; ( len *entry )
342 DW LITERAL, 3, PLUS ; ( len *string )
343 DW SWAP
344 DW EXIT
345
346
swissChilif8849dc2021-12-31 23:15:57 -0800347 DEFWORD_THREADED SHOW_DICT, 'WORDS'
swissChilif7f1e2b2021-12-31 14:42:43 -0800348 DW LATEST, GET ; ( *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800349.LOOP:
swissChilif7f1e2b2021-12-31 14:42:43 -0800350 DW DUP, ENTRY_NAME ; ( *entry len *string)
swissChilif8849dc2021-12-31 23:15:57 -0800351 DW TYPE, SPACE ; ( *entry )
swissChilif7f1e2b2021-12-31 14:42:43 -0800352 DW GET ; ( *prev-entry )
353 DW DUP ; ( *prev-entry *prev-entry )
swissChilif8849dc2021-12-31 23:15:57 -0800354 DW ZEROBRANCH
355 RELATIVE_ADDRESS .DONE
356
357 DW BRANCH ; Back to start!
358 RELATIVE_ADDRESS .LOOP
359.DONE:
360 DW CR, EXIT
swissChili7c626b92022-01-01 23:35:39 -0800361
362
363 DEFWORD_RAW SHOW_STACK, '.S'
364 MOV CX, WORD [CONST_SP_INITIAL]
365 RSPUSH SI
366 STD ; Go backwards
367
368 MOV SI, CX ; Going down
369 SUB SI, 2 ; Just below it
370 SUB CX, SP ; Number of bytes on the stack
371 JLE .DONE ; Below stack bottom (oops!)
372 SHR CX, 1 ; Divide by 2 -- number of cells
373
374.LOOP:
375 LODSW
376 PUSH CX ; Clobbered
377 CALL DOT_INT
378 POP CX
379
380 MOV DX, ' '
381 WRITECOUT
382
383 LOOP .LOOP
384
385.DONE:
386 MOV DX, CRLF_MSG
387 WRITESOUT
388
389 RSPOP SI
390 CLD
391 NEXT
392
393
394 DEFWORD_THREADED DUMP_IMAGE, 'DUMP-IMAGE'
395 DW LITERAL, F_WRITE ; ( *string len flags )
396 DW OPEN_FILE ; ( handle )
397 DW DUP ; ( handle handle )
398 DW LITERAL, 100h ; ( handle handle *start )
399 DW SWAP, HERE, GET ; ( handle *start handle *here )
400 DW SWAP, FILE_WRITE_RANGE ; ( handle )
401 DW CLOSE_FILE ; ( )
402 DW EXIT