blob: d180f8dc43071dfdf8913b8093dcd334fc99d5b5 [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_IMMED: ; ( cfa immediate? )
268 DW DROP ; ( cfa )
swissChilie4d2e282022-01-04 22:22:27 -0800269.WORD_COMPILE_IMMED:
swissChilif7f1e2b2021-12-31 14:42:43 -0800270 DW EXECUTE ; ( )
271 DW EXIT
272
273.NUM: ; ( addr len 0 )
274 DW DROP ; ( addr len )
275 DW NUMBER ; ( number unparsed )
swissChilif8849dc2021-12-31 23:15:57 -0800276 DW ZEROBRANCH ; ( number )
277 RELATIVE_ADDRESS .NUMOK
swissChilif7f1e2b2021-12-31 14:42:43 -0800278
swissChilif8849dc2021-12-31 23:15:57 -0800279 INCLUDE_STRING 'Word is neither defined nor a number'
280 DW TYPE, CR ; ( number )
281 DW DROP, EXIT ; ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800282
283.NUMOK:
284 ;; ( number )
285 DW STATE, GET ; ( number STATE )
swissChilif8849dc2021-12-31 23:15:57 -0800286 DW ZEROBRANCH ; ( number )
287 RELATIVE_ADDRESS .NUM_IMMED
swissChilif7f1e2b2021-12-31 14:42:43 -0800288
289 DW LITERAL, LITERAL ; ( number LITERAL )
290 DW COMMA, COMMA ; ( )
291
swissChilif8849dc2021-12-31 23:15:57 -0800292.NUM_IMMED: ; ( number ) or ( )
swissChilif7f1e2b2021-12-31 14:42:43 -0800293 DW EXIT
294
swissChilif7f1e2b2021-12-31 14:42:43 -0800295
swissChilif8849dc2021-12-31 23:15:57 -0800296 ;; Jump to the word specified by the CFA on the stack
swissChilif7f1e2b2021-12-31 14:42:43 -0800297 DEFWORD_RAW EXECUTE, 'EXECUTE'
298 POP AX
299 MOV BX, AX
300 JMP [BX]
301
302
303 ;; TODO: await newline
304 DEFWORD_THREADED QUIT, 'QUIT'
swissChilif8849dc2021-12-31 23:15:57 -0800305.START:
swissChilif7f1e2b2021-12-31 14:42:43 -0800306 DW INTERPRET
swissChilif8849dc2021-12-31 23:15:57 -0800307 DW BRANCH
308 RELATIVE_ADDRESS .START
swissChilif7f1e2b2021-12-31 14:42:43 -0800309
310
311 DEFWORD_THREADED COLON, ':'
swissChilif8849dc2021-12-31 23:15:57 -0800312 DW CREATE
swissChilif7f1e2b2021-12-31 14:42:43 -0800313 DW LITERAL, DOCOL, COMMA
314 DW LATEST, GET, HIDDEN
315 DW RIGHTBRACKET
316 DW EXIT
317
318
319 DEFWORD_THREADED_IMMED SEMICOLON, ';'
320 DW LITERAL, EXIT, COMMA
321 DW LATEST, GET, HIDDEN
322 DW LEFTBRACKET
323 DW EXIT
324
325
326 ;; ( *entry -- len *string )
swissChilif8849dc2021-12-31 23:15:57 -0800327 DEFWORD_THREADED ENTRY_NAME, 'ENTRY->NAME'
swissChilif7f1e2b2021-12-31 14:42:43 -0800328 DW DUP ; ( *entry *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800329 DW LITERAL, 2, PLUS ; ( *entry *len/flags )
330 DW GETCHAR ; ( *entry len/flags )
331 DW LITERAL, LENGTH_MASK, AND ; ( *entry len )
swissChilif7f1e2b2021-12-31 14:42:43 -0800332 DW SWAP ; ( len *entry )
333 DW LITERAL, 3, PLUS ; ( len *string )
334 DW SWAP
335 DW EXIT
336
337
swissChilif8849dc2021-12-31 23:15:57 -0800338 DEFWORD_THREADED SHOW_DICT, 'WORDS'
swissChilif7f1e2b2021-12-31 14:42:43 -0800339 DW LATEST, GET ; ( *entry )
swissChilif8849dc2021-12-31 23:15:57 -0800340.LOOP:
swissChilif7f1e2b2021-12-31 14:42:43 -0800341 DW DUP, ENTRY_NAME ; ( *entry len *string)
swissChilif8849dc2021-12-31 23:15:57 -0800342 DW TYPE, SPACE ; ( *entry )
swissChilif7f1e2b2021-12-31 14:42:43 -0800343 DW GET ; ( *prev-entry )
344 DW DUP ; ( *prev-entry *prev-entry )
swissChilif8849dc2021-12-31 23:15:57 -0800345 DW ZEROBRANCH
346 RELATIVE_ADDRESS .DONE
347
348 DW BRANCH ; Back to start!
349 RELATIVE_ADDRESS .LOOP
350.DONE:
351 DW CR, EXIT
swissChili7c626b92022-01-01 23:35:39 -0800352
353
354 DEFWORD_RAW SHOW_STACK, '.S'
355 MOV CX, WORD [CONST_SP_INITIAL]
356 RSPUSH SI
357 STD ; Go backwards
358
359 MOV SI, CX ; Going down
360 SUB SI, 2 ; Just below it
361 SUB CX, SP ; Number of bytes on the stack
362 JLE .DONE ; Below stack bottom (oops!)
363 SHR CX, 1 ; Divide by 2 -- number of cells
364
365.LOOP:
366 LODSW
367 PUSH CX ; Clobbered
368 CALL DOT_INT
369 POP CX
370
371 MOV DX, ' '
372 WRITECOUT
373
374 LOOP .LOOP
375
376.DONE:
377 MOV DX, CRLF_MSG
378 WRITESOUT
379
380 RSPOP SI
381 CLD
382 NEXT
383
384
385 DEFWORD_THREADED DUMP_IMAGE, 'DUMP-IMAGE'
386 DW LITERAL, F_WRITE ; ( *string len flags )
387 DW OPEN_FILE ; ( handle )
388 DW DUP ; ( handle handle )
389 DW LITERAL, 100h ; ( handle handle *start )
390 DW SWAP, HERE, GET ; ( handle *start handle *here )
391 DW SWAP, FILE_WRITE_RANGE ; ( handle )
392 DW CLOSE_FILE ; ( )
393 DW EXIT