1 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; and now
for something completely different
...
5 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6 ;; Z80 Assembler
: label manager
7 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 we
'll do one pass, so we need to record info for all forward references.
11 we could as well record *each* label reference to create cross-ref reports.
16 vocab
-if-none
(asm
-labels
)
18 vocab
-if-none asm
-labels
26 0 value postpone
-expr
-list
28 // record
: prev
, expr
-cfa
, fixer
-cfa
, fix
-disp
, fix
-addr
29 : remember
-expr
( fix
-addr fix
-disp fixer
-cfa expr
-cfa
-- )
30 \
." *** new postponed expression!" cr
32 postpone
-expr
-list forth
:, forth
:, forth
:, forth
:, forth
:,
33 r
> to postpone
-expr
-list
37 defer
(eval
-expr
-cfa
) ( cfa
-- res TRUE
/ error
-code FALSE
)
38 defer
(err
-undefined?
) ( error
-- bool
)
39 defer
(err
-message
) ( error
-- addr count
)
41 ;; if set
, we are resolving
"@@"
42 ;; in this calse
, "get" should
return current
"@@" value instead of failing
43 false value resolve
-nameless
45 // record
: prev
, expr
-cfa
, fixer
-cfa
, fix
-disp
, fix
-addr
46 : resolve
-exprs
( -- )
47 ['] postpone-expr-list cfa->pfa >r
48 postpone-expr-list ( curr | prev )
50 dup cell+ @ (eval-expr-cfa) if
53 dup 3 +cells @ to fix-disp
54 dup 4 +cells @ to fix-pc
56 ;; remove this expression it was succesfully resolved
58 \ ." *** LABEL FIXUP!" cr
60 dup (err-undefined?) if drop
61 else (err-message) error
66 false to resolve-nameless
70 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73 def: ltype-unknown ;; this label was used, but not defined yet
74 def: ltype-var ;; "= value" label, variable
75 def: ltype-equ ;; "equ value" label, constant
76 def: ltype-code ;; code label
77 def: ltype-data ;; data label
81 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82 ;; file info, to avoid allocating file name for each line
84 FileInfo obj-value: next
85 field: fname ;; handle to file name string
88 method: init-append ( -- )
89 method: name-str ( -- addr count )
92 FileInfo oof:obj-value file-info-head
94 FileInfo oof:method: init-append ( -- )
95 0 (include-file-id) to id
97 0 handle:new-init to fname
98 oof:value-of: file-info-head to next
99 self to file-info-head
102 FileInfo oof:method: name-str ( -- addr count )
103 fname dup handle:size@
107 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
108 ;; file reference: info and line
110 FileInfo obj-value: file ;; reference file
111 field: line ;; reference file line
113 method: init ( -- ) \ defined way below ;-)
114 method: name-str ( -- addr count )
119 FileRef oof:method: name-str ( -- addr count )
123 ;; print file and line
124 FileRef oof:method: print ( -- )
125 name-str xtype [char] : emit
130 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
133 0 obj-value: info-head ;; LabelRef
134 field: nfa ;; word nfa, to get a name
135 field: type ;; see above
136 field: value ;; label value
137 FileRef obj-value: set-at ;; last initialised at
139 method: init ( nfa -- )
140 method: type! ( type -- )
141 method: value! ( value -- )
142 method: defined-here ( -- )
143 method: new-ref ( -- ) \ defined way below ;-)
144 method: info-head@ ( -- info-head )
145 method: set-at@ ( -- set-at )
146 method: name ( -- addr count )
149 Label oof:method: init ( nfa -- ) to nfa ltype-unknown to type ;
150 Label oof:method: type! ( type -- ) to type ;
151 Label oof:method: value! ( value -- ) to value ;
152 Label oof:method: defined-here ( -- ) FileRef oof:allot to set-at set-at init ;
153 Label oof:method: info-head@ ( -- ) -> info-head @ ;
154 Label oof:method: set-at@ ( -- ) -> set-at @ ;
155 Label oof:method: name ( -- addr count ) nfa id-count ;
158 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159 ;; each label reference will be recorded
160 ;; it is used both to create reference file, and to show
161 ;; diagnostics on undefined labels
163 LabelRef obj-value: prev ;; next info struct addr, or 0
164 Label obj-value: owner ;; owner of this struct
165 field: zx-pc$ ;; pc$ from asm-emit
166 field: zx-pc ;; pc from asm-emit
167 field: zx-emit-pc ;; disp from asm-emit
168 FileRef obj-value: ref ;; file reference
170 method: init ( owner prev -- )
171 method: prev@ ( -- prev )
172 method: ref@ ( -- ref )
175 LabelRef oof:method: init ( owner prev -- )
177 FileRef oof:allot to ref
179 asm-emit:pc$ to zx-pc$
181 asm-emit:emit-pc to zx-emit-pc
184 LabelRef oof:method: prev@ ( -- prev ) -> prev @ ;
185 LabelRef oof:method: ref@ ( -- ref ) -> ref @ ;
188 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
189 LabelRef Label oof:bind-field: info-head
191 ;; now we can define the method
192 Label oof:method: new-ref ( -- )
193 LabelRef oof:allot >r
194 self -> info-head @ r@ oof:invoke: LabelRef init
199 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
200 ;; return FileInfo for the current source file
201 ;; will reuse an existing one, or create a new one if required
202 : curr-file-info ( -- FileInfo )
203 oof:value-of: file-info-head
207 dup oof:invoke: FileInfo id 0 (include-file-id) = if exit endif
208 oof:invoke: FileInfo next
210 ;; not found, want a new struct
211 FileInfo oof:allot oof:invoke: FileInfo init-append
212 oof:value-of: file-info-head
216 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217 ;; and finally, we can define this method
218 FileRef oof:method: init ( -- )
219 curr-file-info to file
220 0 (include-file-line) to line
224 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
227 ;; last "@@"/"$$" label value
228 -1 value last-f/b-label
230 ;; local labels (starting with dot) will be prefixed with this one
231 Label oof:obj-value global-prefix
234 create temp-name-buf 256 cell+ allot create;
236 : >temp-buf ( addr count -- )
237 dup 1 255 within " label name too long" ?not-error
238 dup temp-name-buf ! temp-name-buf cell+ swap move
241 : temp-buf+cc ( addr count -- )
242 dup 1 255 within " label name too long" ?not-error
243 dup temp-name-buf @ + dup 1 255 within " label name too long" ?not-error
244 >r temp-name-buf count + swap move
248 : temp-buf-cc@ ( -- addr count )
254 : f/b-label? ( addr count -- bool )
256 w@ dup [ [char] @ dup 8 lsh or ] imm-literal =
257 swap [ [char] $ dup 8 lsh or ] imm-literal = or
258 else drop false endif
261 ;; "@f", "$f", "@b", "$b"?
262 ;; 0: nope; -1: back; 1: forward
263 : fref-label? ( addr count -- flag )
265 dup c@ dup [char] @ = swap [char] $ = or if
266 1+ c@ string:char-upper case
275 : fref-f/b-label? ( addr count -- bool )
276 2dup f/b-label? nrot fref-label? logor
279 : fix-prefix ( addr count -- addr count )
280 dup " empty label name, wtf?" ?not-error
281 2dup fref-f/b-label? ifnot
283 [char] . of ;; local label (starts with a dot)
284 oof:value-of: global-prefix " local label without a global" ?not-error
285 global-prefix name >temp-buf temp-buf+cc temp-buf-cc@
287 [char] @ of ;; "@" means "do not reset global prefix
289 dup " invalid label name" ?not-error
290 over c@ [char] @ = if
292 dup " invalid label name" ?not-error
299 : prefix-set? ( addr count -- bool )
300 drop c@ dup [char] @ <> swap [char] . <> and
304 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
306 : find ( addr count -- pfa TRUE / FALSE )
307 vocid: (asm-labels) find-word-in-voc
308 if cfa->pfa true else false endif
312 : (new-label-ref) ( addr count -- Label )
315 latest-nfa Label oof:allot oof:invoke: Label init
320 ;; note label reference
321 ;; this introduces new label record if there wasn't one
, but
322 ;; will
do nothing
for already existing label records
323 : (ref
) ( addr count
-- Label
)
324 2dup find
if nrot
2drop
325 else ;; create new label word
326 ;; change current vocab
to labels
327 current @
>r vocid
: (asm
-labels
) current
!
329 ;; restore old current vocab
334 : ref
( addr count
-- )
335 2dup fref
-f
/b
-label? ifnot
(ref
) oof
:invoke
: Label new
-ref
340 : defined?
( addr count
-- bool
)
341 find dup
if oof
:invoke
: Label type ltype
-unknown
<> endif
345 : (define
-label
) ( addr count value type
-- )
348 r@ ltype
-code
<> r
> ltype
-data
<> and
" invalid nameless label def" ?error
349 r@
0 65536 within
" invalid nameless label value" ?not
-error
352 true
to resolve
-nameless
354 2dup fref
-label?
" invalid label name" ?error
355 r@ ltype
-code
>= if 2dup prefix
-set?
>r
else 0 >r
endif
357 r
> if dup
to global
-prefix
endif
358 ( Label | value type
)
359 dup oof
:invoke
: Label type
360 dup ltype
-unknown
<> if r@
<> r@ ltype
-var
<> or
" label redefinition" ?error
363 r
> over oof
:invoke
: Label type
!
364 r
> over oof
:invoke
: Label value
!
365 oof
:invoke
: Label defined
-here
370 : define
-var
( addr count value
-- ) ltype
-var
(define
-label
) ;
371 : define
-equ
( addr count value
-- ) ltype
-equ
(define
-label
) ;
372 : define
-code
( addr count value
-- ) ltype
-code
(define
-label
) ;
373 : define
-data
( addr count value
-- ) ltype
-data
(define
-label
) ;
376 ;; create new label info struct
, return label value
(not truncated
)
377 ;; doesn
't record label access
378 : get ( addr count -- value TRUE / FALSE )
379 2dup f/b-label? if 2drop false exit endif
380 2dup fref-label? ?dup if nrot 2drop ;; "@b" or "@f"
381 resolve-nameless if ;; resolving "@@"
382 0< " internal nameless resolver error" ?error -- the thing that should not be
384 dup 0 65536 within " internal nameless resolver error (2)" ?not-error -- assertion
387 -if last-f/b-label +0if last-f/b-label true else false endif ;; backref
392 \ fix-prefix 2dup xtype cr
395 " label not found, wtf?!" error
397 dup oof:invoke: Label type ltype-unknown = if drop false
398 else oof:invoke: Label value true
403 : dump-label-refs ( LabelRef -- )
405 ." ref: " dup oof:invoke: LabelRef ref@ oof:invoke: FileRef print cr
406 oof:invoke: LabelRef prev@
411 vocid: (asm-labels) voc-latest
413 ." === LABEL: " dup lfa->nfa id-count xtype ." ===" cr
415 dup oof:invoke: Label type ltype-unknown <> if
416 dup oof:invoke: Label set-at@
417 ." defined at: " oof:invoke: FileRef print cr
419 dup oof:invoke: Label type ." type: " . cr
420 dup oof:invoke: Label value ." value: " . cr
421 dup oof:invoke: Label info-head@ dump-label-refs
427 ;; check if all labels are defined
428 : check-labels ( -- )
429 postpone-expr-list if
430 vocid: (asm-labels) voc-latest
433 dup oof:invoke: Label type ltype-unknown = if
434 ." UNDEFINED LABEL: " over lfa->nfa id-count xtype cr
435 dup oof:invoke: Label info-head@ dump-label-refs