1 ;; Native x86 GNU
/Linux Forth System
, Direct Threaded Code
2 ;; high
-level structured programming words
4 ;; Copyright
(C
) 2020 Ketmar Dark
// Invisible Vector
6 ;; This
program is free software
: you can redistribute it and
/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation
, version
3 of the License ONLY
.
10 ;; This
program is distributed in the hope that it will be useful
,
11 ;; but WITHOUT ANY WARRANTY
; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE
. See the
13 ;; GNU General Public License
for more details
.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this
program. If not
, see
<http
://www
.gnu
.org
/licenses
/>.
18 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19 ;; alas
, the kernel neeeds them
20 \
0 var
(CSP
) (hidden
)
21 \
: !CSP
( -- ) sp@
(csp
) ! ;
22 \
: ?CSP
( -- ) sp@
(csp
) @
- err
-unfinished
-definition ?error
;
24 \
: ?COMP
( -- ) state @
0= err
-compilation
-only ?error
;
25 \
: ?EXEC
( -- ) state @ err
-execution
-only ?error
;
27 ;; CSP check
for loops
29 sp@
(csp
) @ u
> err
-unpaired
-conditionals ?error
33 <> err
-unpaired
-conditionals ?error
37 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38 : ?ANY
-PAIR
( id v0 v1
-- )
41 and err
-unpaired
-conditionals ?error
44 : ?PAIRS
-ANY
-KEEPID
( id v0 v1
-- id
)
45 >r over
<> ;; ( id v0
<>id | v1
)
46 over r
> <> ;; ( id v0
<>id v1
<>id
)
47 and err
-unpaired
-conditionals ?error
51 ;; doesn
't error out, returns flag instead
52 \ : ?OK-PAIR ( id qid -- true // id false ) over = dup if nip endif ;
55 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67 ;; write "branch to destaddr" address to addr
68 \ hidden:: (BRANCH-ADDR!) ( destaddr addr -- ) ! ;
69 alias ! (BRANCH-ADDR!) (hidden)
70 alias @ (BRANCH-ADDR@) (hidden)
73 ;; reserve room for branch address, return addr suitable for "(RESOLVE-J>)"
74 hidden:: (MARK-J>) ( -- addr )
78 ;; compile "forward jump" from address to HERE
79 ;; addr is the result of "(MARK-J>)"
80 hidden:: (RESOLVE-J>) ( addr -- )
81 here swap (branch-addr!)
85 ;; return addr suitable for "(<J-RESOLVE)"
86 hidden:: (<J-MARK) ( -- addr )
90 ;; patch "forward jump" address to HERE
91 ;; addr is the result of "(<J-MARK)"
92 hidden:: (<J-RESOLVE) ( addr -- )
93 cell n-allot (branch-addr!)
97 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
98 ;; yeah, the kernel has its own implementations, so we can load this in runtime
100 ;; each of these has one argument
101 1 constant (CTLID-IF) (hidden)
102 2 constant (CTLID-ELSE) (hidden)
104 3 constant (CTLID-BEGIN) (hidden)
105 4 constant (CTLID-WHILE) (hidden)
107 5 constant (CTLID-CASE) (hidden)
108 6 constant (CTLID-OF) (hidden)
109 7 constant (CTLID-ENDOF) (hidden)
110 8 constant (CTLID-OTHERWISE) (hidden)
112 9 constant (CTLID-DO) (hidden)
113 10 constant (CTLID-DO-BREAK) (hidden)
114 11 constant (CTLID-DO-CONTINUE) (hidden)
116 12 constant (CTLID-CBLOCK) (hidden)
117 13 constant (CTLID-CBLOCK-INTERP) (hidden)
119 14 constant (CTLID-?DO) (hidden)
121 663 constant (CTLID-SC-COLON) (hidden)
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
139 ;; if negative (not zero)
147 ;; if positive (not zero)
155 ;; if negative or zero
163 ;; if positive or zero
172 ?comp (CTLID-IF) ?pairs
181 (CTLID-IF) (CTLID-ELSE) ?any-pair
188 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
190 ;; you can use as many "while" blocks as you want to
191 ;; any loop can be finished with AGAIN/REPEAT/UNTIL
192 ;; "BREAK" and "CONTINUE" cannot be used inside conditionals yet
201 ;; there might be alot of "while" blocks, pop them all
202 ;; compile jump back to begin
203 hidden:: (END-BEGIN) ( pairs... jumpcfa -- )
204 ;; this is done recursively, because this way i can get rid of `par_resolve_jfwd_over_branch`
205 ;; also, we don't have working loops at this point
, so recursion is the only choice
;-)
220 ;; repeats
while the condition is false
227 ;; repeats while the condition is true
242 hidden:: (COMP-WHILE) ( jumpcfa )
244 >r (CTLID-BEGIN) (CTLID-WHILE) ?pairs-any-keepid r>
261 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
262 ;; alas, i had to use one global var
263 ;; <>0: drop when we'll see CASE
264 ;; set
to 0 by
(CTLID
-OF
) or
(CTLID
-OTHERWISE
)
265 0 value
(B
/C
-CASE
-DROP
) (hidden
)
267 ;; workhorse
for break/continue
271 hidden
:: (BREAK/CONTINUE) ( type
)
273 0 2>r
;; type and counter
274 ;; drop on case by
default
275 1 (to-compile
-time
-only
) (b
/c
-case
-drop
)
278 ;; check
for valid ctlid
279 dup
(CTLID
-DO-CONTINUE) > over
(CTLID
-IF) < or ERR
-INVALID
-BREAK-CONT ?error
280 ;; while not begin and not
do
281 dup
(CTLID
-BEGIN
) = over
(CTLID
-DO) = or not
285 ;; 2dup pardottype
"SAVE: ctlid: " dot pardottype
" addr: " udot cr
287 ;; if we
're in (CTLID-CASE) or in (CTLID-ENDOF), compile DROP
288 dup (CTLID-CASE) = if
291 ;; pardottype " compiling DROP (" dup dot pardottype ")" cr
294 ;; drop on next case by default
295 1 (to-compile-time-only) (b/c-case-drop)
297 dup (CTLID-OF) = over (CTLID-OTHERWISE) = or
299 ;; don't drop on next case by
default
300 0 (to-compile
-time
-only
) (b
/c
-case
-drop
)
302 2r
> 2swap
>r
>r
2+ 2>r
304 ;; return stack contains saved values and counter
309 1 rpick
;; peek the type
312 ;; pardottype
"DO/LOOP: continue" cr
313 ;; coninue
: jump
to (LOOP
)
318 ;; break: drop
do args
, jump over
(LOOP
)
320 ;; pardottype
"DO/LOOP: break" cr
321 compile unloop
;; remove
do args
329 1 rpick
;; i
.e
. peek the type
333 ;; pardottype
"BEGIN: continue" cr
334 dup
;; we still need the address
337 (CTLID
-BEGIN
) ;; restore ctlid
341 ;; pardottype
"BEGIN: break" cr
342 (CTLID
-BEGIN
) ;; restore ctlid
349 ;; move saved values back
to the data stack
350 r
> rdrop
;; drop type
352 ;; dup pardottype
"RESTORE " dot pardottype
"items" cr
359 ;; dup
. over udot cr
370 ;; this has
to be here
374 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
377 ;; addr
(CTLID
-OF
) -- when in
"OF"
378 ;; addr
(CTLID
-ENDOF
) -- when
"ENDOF" compiled
379 ;; 0 (CTLID
-OTHERWISE
) -- when
"OTHERWISE" compiled
380 ;; note that
"(CTLID-ENDOF)"s will be accumulated
, and resolved in
"ENDCASE"
383 hidden
:: (X
-OF
) ( ... word
-to-compare
)
386 (CTLID
-CASE
) (CTLID
-ENDOF
) ?pairs
-any
-keepid
;; we should be in normal CASE
387 \ compile over
;; special compare words will
do this
for us
388 r
> compile
, ;; comparator
395 dup
(CTLID
-OTHERWISE
) = if
396 ;; "otherwise", no drop needed
397 (CTLID
-OTHERWISE
) ?pairs
398 0 ?pairs
;; check dummy argument
400 ;; no
"otherwise", compile DROP
412 0 ?pairs
;; check dummy argument
417 0 (CTLID
-CASE
) ;; with dummy argument
420 : OF
['] forth:(of=) (x-of) ; immediate
421 : NOT-OF ['] forth
:(of
<>) (x
-of
) ; immediate
422 : <OF
['] forth:(of<) (x-of) ; immediate
423 : <=OF ['] forth
:(of
<=) (x
-of
) ; immediate
424 : >OF
['] forth:(of>) (x-of) ; immediate
425 : >=OF ['] forth
:(of
>=) (x
-of
) ; immediate
426 : U
<OF
['] forth:(of-U<) (x-of) ; immediate
427 : U<=OF ['] forth
:(of
-U
<=) (x
-of
) ; immediate
428 : U
>OF
['] forth:(of-U>) (x-of) ; immediate
429 : U>=OF ['] forth
:(of
-U
>=) (x
-of
) ; immediate
430 : &OF
['] forth:(of-and) (x-of) ; immediate
431 : AND-OF ['] forth
:(of
-and
) (x
-of
) ; immediate
432 : ~AND
-OF
['] forth:(of-~and) (x-of) ; immediate
433 : WITHIN-OF ['] forth
:(of
-within
) (x
-of
) ; immediate
434 : BOUNDS
-OF
['] forth:(of-bounds) (x-of) ; immediate
437 ?comp (CTLID-OF) ?pairs
445 (CTLID-CASE) (CTLID-ENDOF) ?pairs-any-keepid
454 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
462 hidden:: (END-LOOP) ( endloopcfa )
463 ;; this is done recursively, because this way i can get rid of `par_resolve_jfwd_over_branch`
470 ;; resolve ?DO jump, if it is there
471 dup (CTLID-?DO) = if drop (resolve-j>) endif
473 ;; "continue" should be compiled before recursion, and "break" after it
475 dup (CTLID-DO-CONTINUE) =
477 ;; patch "continue" branch
478 (CTLID-DO-CONTINUE) ?pairs
482 (CTLID-DO-BREAK) ?pairs
484 ;; here, loop branch already compiled
492 ['] (loop
) (end-loop
)
497 ['] (+loop) (end-loop) ;; +)
509 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
517 ;; interpreting, use temporary dp
518 dp-temp @ err-temp-here-already ?error
519 ;; compile to temporary area
520 dp @ 42666 + dp-temp !
524 (CTLID-CBLOCK-INTERP)
526 ['] (URFORTH
-DOFORTH
-CODEBLOCK
) (call,)
531 dup
(CTLID
-CBLOCK
-INTERP
) =
533 ;; used from the interpreter
534 (CTLID
-CBLOCK
-INTERP
) ?pairs
537 ;; `
(CTLID
-CBLOCK
-INTERP
)` argument is cblock CFA
542 (CTLID
-CBLOCK
) ?pairs