2020-03-27 08:23:45 -04:00
|
|
|
( Inner core. This unit represents core definitions that
|
|
|
|
happen right after native definitions. Before core.fs.
|
|
|
|
|
|
|
|
Unlike core.fs and its followers, this unit isn't self-
|
|
|
|
sustained. Like native defs it uses the machinery of a
|
|
|
|
full Forth interpreter, notably for flow structures.
|
|
|
|
|
|
|
|
Because of that, it has to obey specific rules:
|
|
|
|
|
|
|
|
1. It cannot compile a word from higher layers. Using
|
|
|
|
immediates is fine though.
|
|
|
|
2. If it references a word from this unit or from native
|
|
|
|
definitions, these need to be properly offsetted
|
|
|
|
because their offset at compile time are not the same
|
|
|
|
as their runtime offsets.
|
|
|
|
3. Anything they refer to in the boot binary has to be
|
|
|
|
properly stabilized.
|
|
|
|
4. Make sure that the words you compile are not overridden
|
|
|
|
by the full interpreter.
|
2020-03-30 13:50:53 -04:00
|
|
|
5. When using words as immediates, make sure that they're
|
|
|
|
not defined in icore or, if they are, make sure that
|
|
|
|
they contain no "_c" references.
|
|
|
|
|
|
|
|
All these rules make this unit a bit messy, but this is the
|
|
|
|
price to pay for the awesomeness of self-bootstrapping.
|
2020-03-27 08:23:45 -04:00
|
|
|
)
|
|
|
|
|
2020-03-27 09:32:03 -04:00
|
|
|
( When referencing words from native defs or this very unit,
|
|
|
|
use this compiling word, which subtract the proper offset
|
|
|
|
from the compiled word. That proper offset is:
|
|
|
|
1. Take ROT-header addr, the first native def.
|
|
|
|
2. Subtract _bend, boot's last word.
|
|
|
|
3. That will give us the offset to subtract to get the addr
|
|
|
|
of our word at runtime.
|
|
|
|
|
|
|
|
This means, of course, that any word compiling a _c word
|
|
|
|
can't be executed immediately.
|
2020-03-27 15:33:04 -04:00
|
|
|
|
|
|
|
Also note that because of that "_c" mechanism, it might
|
|
|
|
take two rounds of bootstrapping before the compiled
|
|
|
|
z80c.bin file is "stabilized". That's because the 2nd time
|
|
|
|
around, the recorded offset will have changed.
|
2020-03-27 09:32:03 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
: _c
|
2020-03-27 15:33:04 -04:00
|
|
|
[
|
|
|
|
' ROT
|
2020-03-27 09:32:03 -04:00
|
|
|
6 - ( header )
|
2020-03-27 15:33:04 -04:00
|
|
|
' _bend
|
2020-03-27 09:32:03 -04:00
|
|
|
- ( our offset )
|
2020-03-27 15:33:04 -04:00
|
|
|
LITN
|
|
|
|
]
|
2020-03-27 09:32:03 -04:00
|
|
|
' ( get word )
|
|
|
|
-^ ( apply offset )
|
|
|
|
, ( write! )
|
|
|
|
; IMMEDIATE
|
|
|
|
|
2020-03-30 14:29:21 -04:00
|
|
|
: FLAGS
|
2020-03-30 17:05:00 -04:00
|
|
|
( 52 == FLAGS )
|
|
|
|
[ 52 @ LITN ]
|
2020-03-30 14:29:21 -04:00
|
|
|
;
|
|
|
|
|
2020-03-30 14:49:20 -04:00
|
|
|
: (parse*)
|
2020-03-30 17:05:00 -04:00
|
|
|
( 54 == PARSEPTR )
|
|
|
|
[ 54 @ LITN ]
|
2020-03-30 14:49:20 -04:00
|
|
|
;
|
|
|
|
|
2020-03-30 15:11:23 -04:00
|
|
|
: HERE
|
2020-03-30 17:05:00 -04:00
|
|
|
( 56 == HERE )
|
|
|
|
[ 56 @ LITN ]
|
2020-03-30 15:11:23 -04:00
|
|
|
;
|
|
|
|
|
|
|
|
: CURRENT
|
2020-03-30 17:05:00 -04:00
|
|
|
( 58 == CURRENT )
|
|
|
|
[ 58 @ LITN ]
|
2020-03-30 15:11:23 -04:00
|
|
|
;
|
|
|
|
|
2020-03-30 13:50:53 -04:00
|
|
|
: QUIT
|
2020-03-30 14:29:21 -04:00
|
|
|
0 _c FLAGS _c ! _c (resRS)
|
2020-03-30 17:36:15 -04:00
|
|
|
LIT< INTERPRET _c (find) _c DROP EXECUTE
|
2020-03-30 13:50:53 -04:00
|
|
|
;
|
2020-03-30 08:25:22 -04:00
|
|
|
|
|
|
|
: ABORT _c (resSP) _c QUIT ;
|
2020-03-28 10:11:52 -04:00
|
|
|
|
2020-03-31 15:04:28 -04:00
|
|
|
: = _c CMP _c NOT ;
|
|
|
|
: < _c CMP -1 _c = ;
|
|
|
|
: > _c CMP 1 _c = ;
|
|
|
|
|
|
|
|
: (parsed) ( a -- n f )
|
|
|
|
( read first char outside of the loop. it *has* to be
|
|
|
|
nonzero. )
|
|
|
|
_c DUP _c C@ ( a c )
|
|
|
|
_c DUP _c NOT IF EXIT THEN ( a 0 )
|
|
|
|
( special case: do we have a negative? )
|
|
|
|
_c DUP '-' _c = IF
|
|
|
|
( Oh, a negative, let's recurse and reverse )
|
|
|
|
_c DROP 1 _c + ( a+1 )
|
|
|
|
_c (parsed) ( n f )
|
|
|
|
_c SWAP 0 _c SWAP ( f 0 n )
|
|
|
|
_c - _c SWAP EXIT ( 0-n f )
|
|
|
|
THEN
|
|
|
|
( running result, staring at zero )
|
|
|
|
0 _c SWAP ( a r c )
|
|
|
|
( Loop over chars )
|
|
|
|
BEGIN
|
|
|
|
( parse char )
|
|
|
|
'0' _c -
|
|
|
|
( if bad, return "a 0" )
|
|
|
|
_c DUP 0 _c < IF _c 2DROP 0 EXIT THEN ( bad )
|
|
|
|
_c DUP 9 _c > IF _c 2DROP 0 EXIT THEN ( bad )
|
|
|
|
( good, add to running result )
|
|
|
|
_c SWAP 10 _c * _c + ( a r*10+n )
|
|
|
|
_c SWAP 1 _c + _c SWAP ( a+1 r )
|
|
|
|
( read next char )
|
|
|
|
_c OVER _c C@
|
|
|
|
_c DUP _c NOT UNTIL
|
|
|
|
( we're done and it's a success. We have "a r c", we want
|
|
|
|
"r 1". )
|
|
|
|
_c DROP _c SWAP _c DROP 1
|
|
|
|
;
|
|
|
|
|
2020-03-27 11:49:50 -04:00
|
|
|
( This is only the "early parser" in earlier stages. No need
|
|
|
|
for an abort message )
|
|
|
|
: (parse)
|
2020-03-30 17:26:51 -04:00
|
|
|
_c (parsed) _c NOT IF _c ABORT THEN
|
2020-03-27 11:49:50 -04:00
|
|
|
;
|
|
|
|
|
2020-03-27 12:36:10 -04:00
|
|
|
( a -- )
|
|
|
|
: (print)
|
|
|
|
BEGIN
|
2020-03-30 08:02:20 -04:00
|
|
|
_c DUP ( a a )
|
2020-03-27 12:36:10 -04:00
|
|
|
_c C@ ( a c )
|
|
|
|
( exit if null )
|
2020-03-30 17:26:51 -04:00
|
|
|
_c DUP _c NOT IF _c 2DROP EXIT THEN
|
2020-03-28 10:25:02 -04:00
|
|
|
_c EMIT ( a )
|
2020-03-28 15:33:14 -04:00
|
|
|
1 _c + ( a+1 )
|
2020-03-27 12:36:10 -04:00
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
2020-03-28 09:19:40 -04:00
|
|
|
: (uflw)
|
2020-03-28 10:11:52 -04:00
|
|
|
LIT< stack-underflow _c (print) _c ABORT
|
2020-03-28 09:19:40 -04:00
|
|
|
;
|
|
|
|
|
2020-03-30 08:37:33 -04:00
|
|
|
: C<
|
2020-03-30 17:05:00 -04:00
|
|
|
( 48 == CINPTR )
|
|
|
|
[ 48 @ LITN ] _c @ EXECUTE
|
2020-03-30 08:37:33 -04:00
|
|
|
;
|
|
|
|
|
2020-03-31 15:26:43 -04:00
|
|
|
: ,
|
|
|
|
_c HERE _c @ _c !
|
|
|
|
_c HERE _c @ 2 _c + _c HERE _c !
|
|
|
|
;
|
|
|
|
|
2020-03-27 19:12:46 -04:00
|
|
|
: C,
|
2020-03-30 15:11:23 -04:00
|
|
|
_c HERE _c @ _c C!
|
|
|
|
_c HERE _c @ 1 _c + _c HERE _c !
|
2020-03-27 19:12:46 -04:00
|
|
|
;
|
|
|
|
|
2020-03-28 13:18:43 -04:00
|
|
|
( The NOT is to normalize the negative/positive numbers to 1
|
|
|
|
or 0. Hadn't we wanted to normalize, we'd have written:
|
|
|
|
32 CMP 1 - )
|
2020-03-30 17:26:51 -04:00
|
|
|
: WS? 33 _c CMP 1 _c + _c NOT ;
|
2020-03-28 13:18:43 -04:00
|
|
|
|
2020-03-28 13:02:04 -04:00
|
|
|
: TOWORD
|
|
|
|
BEGIN
|
2020-03-30 17:26:51 -04:00
|
|
|
_c C< _c DUP _c WS? _c NOT IF EXIT THEN _c DROP
|
2020-03-28 13:02:04 -04:00
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
2020-03-28 12:55:22 -04:00
|
|
|
( Read word from C<, copy to WORDBUF, null-terminate, and
|
|
|
|
return, make HL point to WORDBUF. )
|
|
|
|
: WORD
|
2020-03-30 17:05:00 -04:00
|
|
|
( 38 == WORDBUF )
|
|
|
|
[ 38 @ LITN ] ( a )
|
2020-03-28 13:02:04 -04:00
|
|
|
_c TOWORD ( a c )
|
2020-03-28 12:55:22 -04:00
|
|
|
BEGIN
|
|
|
|
( We take advantage of the fact that char MSB is
|
|
|
|
always zero to pre-write our null-termination )
|
2020-03-30 14:09:39 -04:00
|
|
|
_c OVER _c ! ( a )
|
2020-03-28 15:33:14 -04:00
|
|
|
1 _c + ( a+1 )
|
2020-03-30 08:37:33 -04:00
|
|
|
_c C< ( a c )
|
2020-03-30 08:02:20 -04:00
|
|
|
_c DUP _c WS?
|
2020-03-28 12:55:22 -04:00
|
|
|
UNTIL
|
|
|
|
( a this point, PS is: a WS )
|
|
|
|
( null-termination is already written )
|
2020-03-30 13:54:46 -04:00
|
|
|
_c 2DROP
|
2020-03-30 17:05:00 -04:00
|
|
|
[ 38 @ LITN ]
|
2020-03-28 12:55:22 -04:00
|
|
|
;
|
|
|
|
|
2020-03-27 16:52:42 -04:00
|
|
|
: (entry)
|
2020-03-30 17:59:30 -04:00
|
|
|
_c HERE _c @ ( h )
|
2020-03-28 12:55:22 -04:00
|
|
|
_c WORD ( h s )
|
2020-03-30 17:59:30 -04:00
|
|
|
_c SCPY ( h )
|
2020-03-27 16:52:42 -04:00
|
|
|
( Adjust HERE -1 because SCPY copies the null )
|
2020-03-30 15:11:23 -04:00
|
|
|
_c HERE _c @ 1 _c - ( h h' )
|
|
|
|
_c DUP _c HERE _c ! ( h h' )
|
2020-03-30 08:06:11 -04:00
|
|
|
_c SWAP _c - ( sz )
|
2020-03-27 16:52:42 -04:00
|
|
|
( write prev value )
|
2020-03-31 15:26:43 -04:00
|
|
|
_c HERE _c @ _c CURRENT _c @ _c - _c ,
|
2020-03-27 16:52:42 -04:00
|
|
|
( write size )
|
2020-03-27 19:12:46 -04:00
|
|
|
_c C,
|
2020-03-30 15:11:23 -04:00
|
|
|
_c HERE _c @ _c CURRENT _c !
|
2020-03-27 16:52:42 -04:00
|
|
|
;
|
|
|
|
|
2020-03-28 12:55:22 -04:00
|
|
|
: INTERPRET
|
|
|
|
BEGIN
|
|
|
|
_c WORD
|
2020-03-30 17:36:15 -04:00
|
|
|
_c (find)
|
2020-03-28 12:55:22 -04:00
|
|
|
IF
|
2020-03-30 14:29:21 -04:00
|
|
|
1 _c FLAGS _c !
|
2020-03-28 12:55:22 -04:00
|
|
|
EXECUTE
|
2020-03-30 14:29:21 -04:00
|
|
|
0 _c FLAGS _c !
|
2020-03-28 12:55:22 -04:00
|
|
|
ELSE
|
2020-03-30 14:49:20 -04:00
|
|
|
_c (parse*) _c @ EXECUTE
|
2020-03-28 12:55:22 -04:00
|
|
|
THEN
|
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
|
|
|
: BOOT
|
2020-03-30 17:36:15 -04:00
|
|
|
LIT< (parse) _c (find) _c DROP _c (parse*) _c !
|
|
|
|
LIT< (c<) _c (find) _c
|
|
|
|
NOT IF LIT< KEY _c (find) _c DROP THEN
|
2020-03-30 17:05:00 -04:00
|
|
|
( 48 == CINPTR )
|
|
|
|
[ 48 @ LITN ] _c !
|
2020-03-30 17:36:15 -04:00
|
|
|
LIT< (c<$) _c (find) IF EXECUTE ELSE _c DROP THEN
|
2020-03-28 12:55:22 -04:00
|
|
|
_c INTERPRET
|
|
|
|
;
|
|
|
|
|
2020-03-30 13:50:53 -04:00
|
|
|
( LITN has to be defined after the last immediate usage of
|
|
|
|
it to avoid bootstrapping issues )
|
|
|
|
: LITN
|
2020-03-30 17:05:00 -04:00
|
|
|
( 32 == NUMBER )
|
2020-03-31 15:26:43 -04:00
|
|
|
32 _c , _c ,
|
2020-03-30 13:50:53 -04:00
|
|
|
;
|
|
|
|
|
2020-03-27 16:16:57 -04:00
|
|
|
( : and ; have to be defined last because it can't be
|
|
|
|
executed now also, they can't have their real name
|
|
|
|
right away )
|
|
|
|
|
|
|
|
: X
|
2020-03-27 16:52:42 -04:00
|
|
|
_c (entry)
|
2020-03-28 10:38:05 -04:00
|
|
|
( We cannot use LITN as IMMEDIATE because of bootstrapping
|
2020-03-30 17:05:00 -04:00
|
|
|
issues. 32 == NUMBER 14 == compiledWord )
|
2020-03-31 15:26:43 -04:00
|
|
|
[ 32 , 14 , ] _c ,
|
2020-03-27 16:16:57 -04:00
|
|
|
BEGIN
|
2020-03-28 12:55:22 -04:00
|
|
|
_c WORD
|
2020-03-30 17:36:15 -04:00
|
|
|
_c (find)
|
2020-03-27 16:16:57 -04:00
|
|
|
( is word )
|
2020-03-31 15:26:43 -04:00
|
|
|
IF _c DUP _c IMMED? IF EXECUTE ELSE _c , THEN
|
2020-03-27 16:16:57 -04:00
|
|
|
( maybe number )
|
2020-03-30 14:49:20 -04:00
|
|
|
ELSE _c (parse*) _c @ EXECUTE _c LITN THEN
|
2020-03-27 16:16:57 -04:00
|
|
|
AGAIN
|
|
|
|
; IMMEDIATE
|
|
|
|
|
|
|
|
: Y
|
2020-03-31 15:26:43 -04:00
|
|
|
['] EXIT _c ,
|
2020-03-30 13:57:06 -04:00
|
|
|
_c R> _c DROP ( exit : )
|
2020-03-27 11:27:40 -04:00
|
|
|
; IMMEDIATE
|
|
|
|
|
2020-03-27 16:16:57 -04:00
|
|
|
( Give ":" and ";" their real name )
|
|
|
|
':' ' X 4 - C!
|
|
|
|
';' ' Y 4 - C!
|
2020-03-27 11:27:40 -04:00
|
|
|
|