1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; UrForth level
1: self
-hosting
32-bit Forth compiler
3 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 voc
-set
-active COMPILER
11 sp@
(csp
) @ u
> err
-unpaired
-conditionals ?error
15 <> err
-unpaired
-conditionals ?error
19 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 : ?ANY
-PAIR
( id v0 v1
-- )
23 and err
-unpaired
-conditionals ?error
26 : ?PAIRS
-ANY
-KEEPID
( id v0 v1
-- id
)
27 >r over
<> ;; ( id v0
<>id | v1
)
28 over r
> <> ;; ( id v0
<>id v1
<>id
)
29 and err
-unpaired
-conditionals ?error
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45 ;; write "branch to destaddr" address
to addr
46 ;; : (BRANCH
-ADDR
!) ( destaddr addr
-- ) ! ; (hidden
)
47 alias
! (BRANCH
-ADDR
!)
50 ;; read branch address
51 alias @
(BRANCH
-ADDR@
) ( addr
-- dest
)
55 ;; reserve room
for branch address
, return addr suitable
for "(RESOLVE-J>)"
56 : (MARK
-J
>) ( -- addr
)
60 ;; compile
"forward jump" from address
to HERE
61 ;; addr is the result of
"(MARK-J>)"
62 : (RESOLVE
-J
>) ( addr
-- )
63 here swap
(branch
-addr
!)
67 ;; return addr suitable
for "(<J-RESOLVE)"
68 : (<J
-MARK
) ( -- addr
)
72 ;; patch
"forward jump" address
to HERE
73 ;; addr is the result of
"(<J-MARK)"
74 : (<J
-RESOLVE
) ( addr
-- )
75 cell n
-allot
(branch
-addr
!)
79 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
80 ;; yeah
, the kernel has its own implementations
, so we can load this in runtime
82 ;; each of these has one argument
85 value
(CTLID
-IF) (hidden
)
86 value
(CTLID
-ELSE) (hidden
)
88 value
(CTLID
-BEGIN
) (hidden
)
89 value
(CTLID
-WHILE) (hidden
)
91 value
(CTLID
-CASE
) (hidden
)
92 value
(CTLID
-OF
) (hidden
)
93 value
(CTLID
-ENDOF
) (hidden
)
94 value
(CTLID
-OTHERWISE
) (hidden
)
96 value
(CTLID
-DO) (hidden
)
97 value
(CTLID
-DO-BREAK) (hidden
)
98 value
(CTLID
-DO-CONTINUE) (hidden
)
100 value
(CTLID
-CBLOCK
) (hidden
)
101 value
(CTLID
-CBLOCK
-INTERP
) (hidden
)
103 value
(CTLID
-?
DO) (hidden
)
106 value
(CTLID
-SC
-COLON
) (hidden
)
109 value
(XX
-CTLID
-LAST
) (hidden
)
112 (XX
-CTLID
-LAST
) var
(XX
-CTLID
-NEXT
-USER
) (hidden
)
114 : allocate
-ctlid
( -- id
) (xx
-ctlid
-next
-user
) @
(xx
-ctlid
-next
-user
) 1+! ;
117 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
119 ;; there might be alot of
"while" blocks
, pop them all
120 ;; compile jump back
to begin
121 : (END-BEGIN
) ( pairs
... jumpcfa
-- )
122 ;; this is done recursively
, because this way i can get rid of `par_resolve_jfwd_over_branch`
123 ;; also
, we don
't have working loops at this point, so recursion is the only choice ;-)
125 over (CTLID-BEGIN) = if
137 : (COMP-WHILE) ( jumpcfa )
139 >r (CTLID-BEGIN) (CTLID-WHILE) ?pairs-any-keepid r>
146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147 ;; alas, i had to use one global var
148 ;; <>0: drop when we'll see CASE
149 ;; set
to 0 by
(CTLID
-OF
) or
(CTLID
-OTHERWISE
)
150 $value
"(B/C-CASE-DROP)" 0
153 ;; workhorse
for break/continue
157 : (BREAK/CONTINUE) ( type
)
159 0 2>r
;; type and counter
160 ;; drop on case by
default
164 ;; check
for valid ctlid
165 dup
(CTLID
-DO-CONTINUE) > over
(CTLID
-IF) < or ERR
-INVALID
-BREAK-CONT ?error
166 ;; while not begin and not
do
167 dup
(CTLID
-BEGIN
) = over
(CTLID
-DO) = or not
171 ;; 2dup pardottype
"SAVE: ctlid: " dot pardottype
" addr: " udot cr
173 ;; if we
're in (CTLID-CASE) or in (CTLID-ENDOF), compile DROP
174 dup (CTLID-CASE) = if
177 ;; pardottype " compiling DROP (" dup dot pardottype ")" cr
180 ;; drop on next case by default
183 dup (CTLID-OF) = over (CTLID-OTHERWISE) = or
184 if 0 to (b/c-case-drop) endif ;; don't drop on next case by
default
185 2r
> 2swap
>r
>r
2+ 2>r
187 ;; return stack contains saved values and counter
191 1 rpick
;; peek the type
194 ;; pardottype
"DO/LOOP: continue" cr
195 ;; coninue
: jump
to (LOOP
)
200 ;; break: drop
do args
, jump over
(LOOP
)
202 ;; pardottype
"DO/LOOP: break" cr
203 compile unloop
;; remove
do args
211 1 rpick
;; i
.e
. peek the type
215 ;; pardottype
"BEGIN: continue" cr
216 dup
;; we still need the address
219 (CTLID
-BEGIN
) ;; restore ctlid
223 ;; pardottype
"BEGIN: break" cr
224 (CTLID
-BEGIN
) ;; restore ctlid
231 ;; move saved values back
to the data stack
232 r
> rdrop
;; drop type
234 ;; dup pardottype
"RESTORE " dot pardottype
"items" cr
235 begin ?dup
while r
> swap
1- repeat
237 ;; dup
. over udot cr
241 : (END-LOOP
) ( endloopcfa
)
242 ;; this is done recursively
, because this way i can get rid of `par_resolve_jfwd_over_branch`
248 ;; resolve ?
DO jump
, if it is there
249 dup
(CTLID
-?
DO) = if drop
(resolve
-j
>) endif
251 ;; "continue" should be compiled before recursion
, and
"break" after it
253 dup
(CTLID
-DO-CONTINUE) = if
254 ;; patch
"continue" branch
255 (CTLID
-DO-CONTINUE) ?pairs
259 (CTLID
-DO-BREAK) ?pairs
261 ;; here
, loop branch already compiled
268 : (X
-OF
) ( ... word
-to-compare
)
271 (CTLID
-CASE
) (CTLID
-ENDOF
) ?pairs
-any
-keepid
;; we should be in normal CASE
272 \ compile over
;; special compare words will
do this
for us
273 r
> compile
, ;; comparator
280 dup
(CTLID
-OTHERWISE
) = if
281 ;; "otherwise", no drop needed
282 (CTLID
-OTHERWISE
) ?pairs
283 0 ?pairs
;; check dummy argument
285 ;; no
"otherwise", compile DROP
297 0 ?pairs
;; check dummy argument
304 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
319 ;; if negative
(not zero
)
327 ;; if positive
(not zero
)
336 compiler
:?comp compiler
:(CTLID
-IF) compiler
:?pairs
339 swap compiler
:(resolve
-j
>)
340 compiler
:(CTLID
-ELSE)
345 compiler
:(CTLID
-IF) compiler
:(CTLID
-ELSE) compiler
:?any
-pair
346 compiler
:(resolve
-j
>)
352 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
354 ;; you can use as many
"while" blocks as you want
to
355 ;; any loop can be finished with AGAIN
/REPEAT
/UNTIL
356 ;; "BREAK" and
"CONTINUE" cannot be used inside conditionals yet
362 compiler
:(CTLID
-BEGIN
)
365 ;; repeats
while the condition is false
372 ;; repeats while the condition is true
379 ;; repeats
while the number
if positive
386 ;; repeats while the number if negative
403 compiler
:(comp
-while)
408 compiler:(comp-while)
413 compiler
:(comp
-while)
418 compiler:(comp-while)
423 1 compiler:(break/continue)
427 0 compiler:(break/continue)
430 ;; this has to be here
434 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
437 ;; addr (CTLID-OF) -- when in "OF"
438 ;; addr (CTLID-ENDOF) -- when "ENDOF" compiled
439 ;; 0 (CTLID-OTHERWISE) -- when "OTHERWISE" compiled
440 ;; note that "(CTLID-ENDOF)"s will be accumulated, and resolved in "ENDCASE"
445 0 compiler:(CTLID-CASE) ;; with dummy argument
448 : OF ['] forth
:(of
=) compiler
:(x
-of
) ; immediate
449 : NOT
-OF
['] forth:(of<>) compiler:(x-of) ; immediate
450 : <OF ['] forth
:(of
<) compiler
:(x
-of
) ; immediate
451 : <=OF
['] forth:(of<=) compiler:(x-of) ; immediate
452 : >OF ['] forth
:(of
>) compiler
:(x
-of
) ; immediate
453 : >=OF
['] forth:(of>=) compiler:(x-of) ; immediate
454 : U<OF ['] forth
:(of
-U
<) compiler
:(x
-of
) ; immediate
455 : U
<=OF
['] forth:(of-U<=) compiler:(x-of) ; immediate
456 : U>OF ['] forth
:(of
-U
>) compiler
:(x
-of
) ; immediate
457 : U
>=OF
['] forth:(of-U>=) compiler:(x-of) ; immediate
458 : &OF ['] forth
:(of
-and
) compiler
:(x
-of
) ; immediate
459 : AND
-OF
['] forth:(of-and) compiler:(x-of) ; immediate
460 : ~AND-OF ['] forth
:(of
-~and
) compiler
:(x
-of
) ; immediate
461 : WITHIN
-OF
['] forth:(of-within) compiler:(x-of) ; immediate
462 : BOUNDS-OF ['] forth
:(of
-bounds
) compiler
:(x
-of
) ; immediate
465 compiler
:?comp compiler
:(CTLID
-OF
) compiler
:?pairs
468 swap compiler
:(resolve
-j
>)
469 compiler
:(CTLID
-ENDOF
)
473 compiler
:(CTLID
-CASE
) compiler
:(CTLID
-ENDOF
) compiler
:?pairs
-any
-keepid
474 0 compiler
:(CTLID
-OTHERWISE
)
483 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
493 ['] (loop) compiler:(end-loop)
498 ['] (+loop
) compiler
:(end-loop
)
510 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
511 ;; "FOR" is
for loops with
"step by 1", from
0