blob: c7edce4dffb242b9790d474d1448c730953fe8d0 [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
88 ;; Code field address
89 DEFWORD_RAW CFA, '>CFA'
90 POP BX
91 ADD BX, 2
92
93 XOR CH, CH
94 MOV CL, BYTE [BX] ; String length
95 AND CL, LENGTH_MASK
96 ADD BX, CX ; Code field address
97 ADD BX, 2 ; 1 to round up, 1 to skip length
98 AND BX, (~1) ; Zero the last bit
99
100
101 PUSH BX
102 NEXT
103
104
105 DEFWORD_THREADED DFA, '>DFA'
106 DW CFA, ADD2, EXIT
107
108
swissChilif8849dc2021-12-31 23:15:57 -0800109 ;; ( *a *b num -- )
110 ;; Copy NUM bytes from A to B
111 DEFWORD_RAW CMOVE, 'CMOVE'
112 RSPUSH SI
113 POP CX
114 POP DI
115 POP SI
116 REP MOVSB
117 RSPOP SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800118 NEXT
119
swissChilif7f1e2b2021-12-31 14:42:43 -0800120
swissChilif8849dc2021-12-31 23:15:57 -0800121 ;; ( a -- b )
122 ;; Round up to even number
123 DEFWORD_RAW ROUND_EVEN, 'ROUND-EVEN'
124 POP AX
125 INC AX
126 AND AX, (~1)
127 PUSH AX
128 NEXT
swissChilif7f1e2b2021-12-31 14:42:43 -0800129
swissChilif7f1e2b2021-12-31 14:42:43 -0800130
swissChilif8849dc2021-12-31 23:15:57 -0800131 DEFWORD_RAW CMOVE_HERE, 'CMOVE,'
132 POP CX
133 RSPUSH SI
swissChilif7f1e2b2021-12-31 14:42:43 -0800134 POP SI
swissChilif8849dc2021-12-31 23:15:57 -0800135 MOV DI, [VAR_HERE]
136 REP MOVSB
137 MOV [VAR_HERE], DI
138 RSPOP SI
139 NEXT
140
141
142 DEFWORD_THREADED CREATE, 'CREATE'
143 DW HERE, GET ; ( *here )
144 DW _WORD ; ( *here *string length )
swissChilif8849dc2021-12-31 23:15:57 -0800145 DW LATEST, GET ; ( *here *string length link )
146 DW COMMA, DUP, CHAR_COMMA ; ( *here *string length )
147 DW CMOVE_HERE ; ( *here )
148 DW HERE, GET ; ( *here *here[new] )
149 DW ROUND_EVEN ; ( here[new,even] )
150 DW HERE, SET ; ( *here )
151 DW LATEST, SET ; ( )
152 DW EXIT
swissChilif7f1e2b2021-12-31 14:42:43 -0800153
154
155 DEFWORD_RAW COMMA, ','
156 POP AX
157 MOV DI, [VAR_HERE]
158 STOSW
159 MOV [VAR_HERE], DI
160 NEXT
161
162
swissChilif8849dc2021-12-31 23:15:57 -0800163 DEFWORD_RAW CHAR_COMMA, 'C,'
164 POP AX
165 MOV DI, [VAR_HERE]
166 STOSB
167 MOV [VAR_HERE], DI
168 NEXT
169
170
swissChilif7f1e2b2021-12-31 14:42:43 -0800171 ;; Switch to interpret mode
172 DEFWORD_RAW_IMMEDIATE LEFTBRACKET, '['
173 MOV WORD [VAR_STATE], 0
174 NEXT
175
176
swissChilif8849dc2021-12-31 23:15:57 -0800177 DEFWORD_RAW RIGHTBRACKET, ']'
swissChilif7f1e2b2021-12-31 14:42:43 -0800178 MOV WORD [VAR_STATE], 1
179 NEXT
180
181
swissChilif8849dc2021-12-31 23:15:57 -0800182 DEFWORD_RAW_IMMEDIATE IMMEDIATE, 'IMMEDIATE'
swissChilif7f1e2b2021-12-31 14:42:43 -0800183 MOV BX, [VAR_LATEST]
184 XOR BYTE [BX + 2], IMMEDIATE_BIT
185 NEXT
186
187
188 ;; LATEST HIDDEN
189 DEFWORD_RAW HIDDEN, 'HIDDEN'
190 POP BX
191 XOR BYTE [BX + 2], HIDDEN_BIT
192 NEXT
193
194
195 ;; HIDE DUP
196 DEFWORD_THREADED HIDE, 'HIDE'
197 DW _WORD, FIND, HIDDEN, EXIT
198
199
200 DEFWORD_THREADED_IMMED TICK, "'"
201 DW _WORD, FIND, CFA, EXIT
202
203
204 DEFWORD_RAW BRANCH, 'BRANCH'
205 LODSW
206 ADD SI, AX
207 NEXT
208
209
210 DEFWORD_RAW ZEROBRANCH, '0BRANCH'
211 POP DX
212 LODSW
213 TEST DX, DX
214 JNZ .NOTZERO
215 ADD SI, AX
216
217.NOTZERO:
218 NEXT
219
220
221 DEFWORD_RAW LITSTRING, 'LITSTRING'
222 LODSW ; Length
223 PUSH SI
224 ADD SI, AX
225 INC SI ; Round up
226 AND SI, (~1)
227 PUSH AX
228 NEXT
229
230
swissChilif8849dc2021-12-31 23:15:57 -0800231 ;; ( entry -- type )
232 ;; 0 = immediate; 1 = normal
233 DEFWORD_THREADED GET_WORD_TYPE, 'WORD-TYPE'
234 DW LITERAL, 2, PLUS ; ( entry+2 )
235 DW GETCHAR ; ( length/flags )
236 DW LITERAL, IMMEDIATE_BIT ; ( length/flags IMMEDIATE_BIT )
237 DW AND ; ( 1=immediate;0=normal )
238 DW LITERAL, IMMEDIATE_BIT
239 DW XOR ; Toggle the bit
240 DW EXIT
241
242
swissChilif7f1e2b2021-12-31 14:42:43 -0800243 DEFWORD_THREADED INTERPRET, 'INTERPRET'
244 DW _WORD ; ( addr len )
245 DW _2DUP, FIND ; ( addr len entry? )
246 DW DUP ; ( addr len entry? entry? )
swissChilif8849dc2021-12-31 23:15:57 -0800247 DW ZEROBRANCH ; ( addr len entry? )
248 RELATIVE_ADDRESS .NUM ; FIND returned 0
swissChilif7f1e2b2021-12-31 14:42:43 -0800249
swissChilif8849dc2021-12-31 23:15:57 -0800250 DW SWAP, DROP, SWAP, DROP ; ( entry )
251 DW DUP, CFA ; ( entry cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800252
swissChilif8849dc2021-12-31 23:15:57 -0800253 DW SWAP ; ( cfa entry )
254 DW GET_WORD_TYPE ; ( cfa immediate? )
swissChilif7f1e2b2021-12-31 14:42:43 -0800255
swissChilif8849dc2021-12-31 23:15:57 -0800256 DW STATE, GET ; ( cfa immediate? interpreting? )
257 ;; In either case evaluate
258 DW ZEROBRANCH ; ( cfa immediate? )
259 RELATIVE_ADDRESS .WORD_IMMED
260 DW ZEROBRANCH ; ( cfa )
261 RELATIVE_ADDRESS .WORD_COMPILE_IMMED
262
263 ;; Compile the word
swissChilif7f1e2b2021-12-31 14:42:43 -0800264 DW COMMA ; Add to HERE
265 DW EXIT
266
swissChilif8849dc2021-12-31 23:15:57 -0800267.WORD_COMPILE_IMMED: ; ( cfa )
268 INCLUDE_STRING 'immediate bit set'
269 DW TYPE, CR
270 DW EXECUTE, EXIT
271
272.WORD_IMMED: ; ( cfa immediate? )
273 DW DROP ; ( cfa )
swissChilif7f1e2b2021-12-31 14:42:43 -0800274 DW EXECUTE ; ( )
275 DW EXIT
276
277.NUM: ; ( addr len 0 )
278 DW DROP ; ( addr len )
279 DW NUMBER ; ( number unparsed )
swissChilif8849dc2021-12-31 23:15:57 -0800280 DW ZEROBRANCH ; ( number )
281 RELATIVE_ADDRESS .NUMOK
swissChilif7f1e2b2021-12-31 14:42:43 -0800282
swissChilif8849dc2021-12-31 23:15:57 -0800283 INCLUDE_STRING 'Word is neither defined nor a number'
284 DW TYPE, CR ; ( number )
285 DW DROP, EXIT ; ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800286
287.NUMOK:
288 ;; ( number )
289 DW STATE, GET ; ( number STATE )
swissChilif8849dc2021-12-31 23:15:57 -0800290 DW ZEROBRANCH ; ( number )
291 RELATIVE_ADDRESS .NUM_IMMED
swissChilif7f1e2b2021-12-31 14:42:43 -0800292
293 DW LITERAL, LITERAL ; ( number LITERAL )
294 DW COMMA, COMMA ; ( )
295
swissChilif8849dc2021-12-31 23:15:57 -0800296.NUM_IMMED: ; ( number ) or ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800297 DW EXIT
298
swissChilif7f1e2b2021-12-31 14:42:43 -0800299
swissChilif8849dc2021-12-31 23:15:57 -0800300 ;; Jump to the word specified by the CFA on the stack
swissChilif7f1e2b2021-12-31 14:42:43 -0800301 DEFWORD_RAW EXECUTE, 'EXECUTE'
302 POP AX
303 MOV BX, AX
304 JMP [BX]
305
306
307 ;; TODO: await newline
308 DEFWORD_THREADED QUIT, 'QUIT'
swissChilif8849dc2021-12-31 23:15:57 -0800309.START:
swissChilif7f1e2b2021-12-31 14:42:43 -0800310 DW INTERPRET
swissChilif8849dc2021-12-31 23:15:57 -0800311 DW BRANCH
312 RELATIVE_ADDRESS .START
swissChilif7f1e2b2021-12-31 14:42:43 -0800313
314
315 DEFWORD_THREADED COLON, ':'
swissChilif8849dc2021-12-31 23:15:57 -0800316 DW CREATE
swissChilif7f1e2b2021-12-31 14:42:43 -0800317 DW LITERAL, DOCOL, COMMA
318 DW LATEST, GET, HIDDEN
319 DW RIGHTBRACKET
320 DW EXIT
321
322
323 DEFWORD_THREADED_IMMED SEMICOLON, ';'
324 DW LITERAL, EXIT, COMMA
325 DW LATEST, GET, HIDDEN
326 DW LEFTBRACKET
327 DW EXIT
328
329
330 ;; ( *entry -- len *string )
swissChilif8849dc2021-12-31 23:15:57 -0800331 DEFWORD_THREADED ENTRY_NAME, 'ENTRY->NAME'
swissChilif7f1e2b2021-12-31 14:42:43 -0800332 DW DUP ; ( *entry *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800333 DW LITERAL, 2, PLUS ; ( *entry *len/flags )
334 DW GETCHAR ; ( *entry len/flags )
335 DW LITERAL, LENGTH_MASK, AND ; ( *entry len )
swissChilif7f1e2b2021-12-31 14:42:43 -0800336 DW SWAP ; ( len *entry )
337 DW LITERAL, 3, PLUS ; ( len *string )
338 DW SWAP
339 DW EXIT
340
341
swissChilif8849dc2021-12-31 23:15:57 -0800342 DEFWORD_THREADED SHOW_DICT, 'WORDS'
swissChilif7f1e2b2021-12-31 14:42:43 -0800343 DW LATEST, GET ; ( *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800344.LOOP:
swissChilif7f1e2b2021-12-31 14:42:43 -0800345 DW DUP, ENTRY_NAME ; ( *entry len *string)
swissChilif8849dc2021-12-31 23:15:57 -0800346 DW TYPE, SPACE ; ( *entry )
swissChilif7f1e2b2021-12-31 14:42:43 -0800347 DW GET ; ( *prev-entry )
348 DW DUP ; ( *prev-entry *prev-entry )
swissChilif8849dc2021-12-31 23:15:57 -0800349 DW ZEROBRANCH
350 RELATIVE_ADDRESS .DONE
351
352 DW BRANCH ; Back to start!
353 RELATIVE_ADDRESS .LOOP
354.DONE:
355 DW CR, EXIT
swissChili7c626b92022-01-01 23:35:39 -0800356
357
358 DEFWORD_RAW SHOW_STACK, '.S'
359 MOV CX, WORD [CONST_SP_INITIAL]
360 RSPUSH SI
361 STD ; Go backwards
362
363 MOV SI, CX ; Going down
364 SUB SI, 2 ; Just below it
365 SUB CX, SP ; Number of bytes on the stack
366 JLE .DONE ; Below stack bottom (oops!)
367 SHR CX, 1 ; Divide by 2 -- number of cells
368
369.LOOP:
370 LODSW
371 PUSH CX ; Clobbered
372 CALL DOT_INT
373 POP CX
374
375 MOV DX, ' '
376 WRITECOUT
377
378 LOOP .LOOP
379
380.DONE:
381 MOV DX, CRLF_MSG
382 WRITESOUT
383
384 RSPOP SI
385 CLD
386 NEXT
387
388
389 DEFWORD_THREADED DUMP_IMAGE, 'DUMP-IMAGE'
390 DW LITERAL, F_WRITE ; ( *string len flags )
391 DW OPEN_FILE ; ( handle )
392 DW DUP ; ( handle handle )
393 DW LITERAL, 100h ; ( handle handle *start )
394 DW SWAP, HERE, GET ; ( handle *start handle *here )
395 DW SWAP, FILE_WRITE_RANGE ; ( handle )
396 DW CLOSE_FILE ; ( )
397 DW EXIT