blob: d7320bd6279ad6e1a7586d7b4363c3d2d1ffdc0f [file] [log] [blame]
swissChilif7f1e2b2021-12-31 14:42:43 -08001;;; Dictionary manipulation & memory management words
2
3 ;; ( 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
23
24.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
109 DEFWORD_RAW CREATE, 'CREATE'
110 POP CX ; Length
111 POP BX ; String
112
113 CALL DO_CREATE
114 NEXT
115
116 ;; CX = Length
117 ;; BX = Address
118 ;;
119 ;; AX, BX, CX, DX, DI clobbered
120DO_CREATE:
121 PUSH SI ; Save SI
122
123 MOV SI, BX
124 MOV DI, [VAR_HERE] ; Top of dictionary
125 MOV DX, DI ; New LATEST
126
127 MOV AX, [VAR_LATEST]
128 STOSW ; Link pointer
129
130 MOV AX, CX ; Length
131 STOSB
132
133 REP MOVSB ; Copy string
134
135 TEST DI, 1
136 JZ .DONE
137
138 INC DI ; Pad
139
140.DONE:
141 MOV [VAR_HERE], DI
142 MOV [VAR_LATEST], DX
143
144 POP SI
145 RET
146
147
148 DEFWORD_RAW COMMA, ','
149 POP AX
150 MOV DI, [VAR_HERE]
151 STOSW
152 MOV [VAR_HERE], DI
153 NEXT
154
155
156 ;; Switch to interpret mode
157 DEFWORD_RAW_IMMEDIATE LEFTBRACKET, '['
158 MOV WORD [VAR_STATE], 0
159 NEXT
160
161
162 DEFWORD_RAW_IMMEDIATE RIGHTBRACKET, ']'
163 MOV WORD [VAR_STATE], 1
164 NEXT
165
166
167 DEFWORD_RAW IMMEDIATE, 'IMMEDIATE'
168 MOV BX, [VAR_LATEST]
169 XOR BYTE [BX + 2], IMMEDIATE_BIT
170 NEXT
171
172
173 ;; LATEST HIDDEN
174 DEFWORD_RAW HIDDEN, 'HIDDEN'
175 POP BX
176 XOR BYTE [BX + 2], HIDDEN_BIT
177 NEXT
178
179
180 ;; HIDE DUP
181 DEFWORD_THREADED HIDE, 'HIDE'
182 DW _WORD, FIND, HIDDEN, EXIT
183
184
185 DEFWORD_THREADED_IMMED TICK, "'"
186 DW _WORD, FIND, CFA, EXIT
187
188
189 DEFWORD_RAW BRANCH, 'BRANCH'
190 LODSW
191 ADD SI, AX
192 NEXT
193
194
195 DEFWORD_RAW ZEROBRANCH, '0BRANCH'
196 POP DX
197 LODSW
198 TEST DX, DX
199 JNZ .NOTZERO
200 ADD SI, AX
201
202.NOTZERO:
203 NEXT
204
205
206 DEFWORD_RAW LITSTRING, 'LITSTRING'
207 LODSW ; Length
208 PUSH SI
209 ADD SI, AX
210 INC SI ; Round up
211 AND SI, (~1)
212 PUSH AX
213 NEXT
214
215
216 DEFWORD_THREADED INTERPRET, 'INTERPRET'
217 DW _WORD ; ( addr len )
218 DW _2DUP, FIND ; ( addr len entry? )
219 DW DUP ; ( addr len entry? entry? )
220 DW ZEROBRANCH, 26 ; ( addr len entry? ); jump to .NUM if
221 ; the entry was not found.
222
223 DW CFA ; ( addr len cfa )
224
225 DW SWAP, DROP ; ( addr cfa )
226 DW SWAP, DROP ; ( cfa )
227 DW STATE, GET ; ( cfa 0|1 )
228
229 DW ZEROBRANCH, 4
230 DW COMMA ; Add to HERE
231 DW EXIT
232
233.WORD_IMMED:
234 DW EXECUTE ; ( )
235 DW EXIT
236
237.NUM: ; ( addr len 0 )
238 DW DROP ; ( addr len )
239 DW NUMBER ; ( number unparsed )
240 DW ZEROBRANCH, 4 ; ( number ); jump to .NUMOK
241
242 DW BRANCH, 18 ; jump to .FAILED
243
244.NUMOK:
245 ;; ( number )
246 DW STATE, GET ; ( number STATE )
247 DW ZEROBRANCH, 8 ; ( number )
248
249 DW LITERAL, LITERAL ; ( number LITERAL )
250 DW COMMA, COMMA ; ( )
251
252.NUM_IMMED: ; ( number )
253 DW EXIT
254
255.FAILED: ; ( number )
256 INCLUDE_STRING $, 'Word is neither defined nor a number'
257 DW TYPE, CR ; ( number )
258 DW DROP, EXIT ; ( )
259
260
261 DEFWORD_RAW EXECUTE, 'EXECUTE'
262 POP AX
263 MOV BX, AX
264 JMP [BX]
265
266
267 ;; TODO: await newline
268 DEFWORD_THREADED QUIT, 'QUIT'
269 DW INTERPRET
270 DW BRANCH, -6
271
272
273 DEFWORD_THREADED COLON, ':'
274 DW _WORD, CREATE
275 DW LITERAL, DOCOL, COMMA
276 DW LATEST, GET, HIDDEN
277 DW RIGHTBRACKET
278 DW EXIT
279
280
281 DEFWORD_THREADED_IMMED SEMICOLON, ';'
282 DW LITERAL, EXIT, COMMA
283 DW LATEST, GET, HIDDEN
284 DW LEFTBRACKET
285 DW EXIT
286
287
288 ;; ( *entry -- len *string )
289 DEFWORD_THREADED ENTRY_NAME, ''
290 DW DUP ; ( *entry *entry )
291 DW LITERAL, 2, PLUS ; ( *entry *len )
292 DW GETCHAR ; ( *entry len )
293 DW SWAP ; ( len *entry )
294 DW LITERAL, 3, PLUS ; ( len *string )
295 DW SWAP
296 DW EXIT
297
298
299 DEFWORD_THREADED SHOW_DICT, '.d'
300 DW LATEST, GET ; ( *entry )
301 DW DUP, ENTRY_NAME ; ( *entry len *string)
302 DW TYPE, CR ; ( *entry )
303 DW GET ; ( *prev-entry )
304 DW DUP ; ( *prev-entry *prev-entry )
305 DW ZEROBRANCH, 2
306 DW BRANCH, -24 ; Back to start!
307 DW EXIT