2020-03-27 23:23:45 +11: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-31 04:50:53 +11:00
|
|
|
5. When using words as immediates, make sure that they're
|
|
|
|
not defined in icore or, if they are, make sure that
|
2020-04-09 22:23:53 +10:00
|
|
|
they are *not* offsetted
|
2020-03-31 04:50:53 +11:00
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
Those rules are mostly met by the "xcomp" unit, which is
|
|
|
|
expected to have been loaded prior to icore and redefines
|
|
|
|
":" and other defining words. So, in other words, when
|
|
|
|
compiling icore, ":" doesn't means what you think it means,
|
|
|
|
go look in xcomp.
|
2020-03-27 23:23:45 +11:00
|
|
|
)
|
|
|
|
|
2020-04-03 00:58:02 +11:00
|
|
|
: RAM+
|
2020-04-09 22:23:53 +10:00
|
|
|
[ RAMSTART LITN ] +
|
2020-03-31 05:29:21 +11:00
|
|
|
;
|
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
: FLAGS 0x08 RAM+ ;
|
|
|
|
: (parse*) 0x0a RAM+ ;
|
|
|
|
: HERE 0x04 RAM+ ;
|
|
|
|
: CURRENT 0x02 RAM+ ;
|
2020-03-31 06:11:23 +11:00
|
|
|
|
2020-03-31 04:50:53 +11:00
|
|
|
: QUIT
|
2020-04-09 22:23:53 +10:00
|
|
|
0 FLAGS ! (resRS)
|
|
|
|
LIT< INTERPRET (find) DROP EXECUTE
|
2020-03-31 04:50:53 +11:00
|
|
|
;
|
2020-03-30 23:25:22 +11:00
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
: ABORT (resSP) QUIT ;
|
2020-03-29 01:11:52 +11:00
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
: = CMP NOT ;
|
|
|
|
: < CMP -1 = ;
|
|
|
|
: > CMP 1 = ;
|
2020-04-01 06:04:28 +11:00
|
|
|
|
|
|
|
: (parsed) ( a -- n f )
|
|
|
|
( read first char outside of the loop. it *has* to be
|
|
|
|
nonzero. )
|
2020-04-09 22:23:53 +10:00
|
|
|
DUP C@ ( a c )
|
|
|
|
DUP NOT IF EXIT THEN ( a 0 )
|
2020-04-01 06:04:28 +11:00
|
|
|
( special case: do we have a negative? )
|
2020-04-09 22:23:53 +10:00
|
|
|
DUP '-' = IF
|
2020-04-01 06:04:28 +11:00
|
|
|
( Oh, a negative, let's recurse and reverse )
|
2020-04-09 22:23:53 +10:00
|
|
|
DROP 1 + ( a+1 )
|
|
|
|
(parsed) ( n f )
|
|
|
|
SWAP 0 SWAP ( f 0 n )
|
|
|
|
- SWAP EXIT ( 0-n f )
|
2020-04-01 06:04:28 +11:00
|
|
|
THEN
|
|
|
|
( running result, staring at zero )
|
2020-04-09 22:23:53 +10:00
|
|
|
0 SWAP ( a r c )
|
2020-04-01 06:04:28 +11:00
|
|
|
( Loop over chars )
|
|
|
|
BEGIN
|
|
|
|
( parse char )
|
2020-04-09 22:23:53 +10:00
|
|
|
'0' -
|
2020-04-01 06:04:28 +11:00
|
|
|
( if bad, return "a 0" )
|
2020-04-09 22:23:53 +10:00
|
|
|
DUP 0 < IF 2DROP 0 EXIT THEN ( bad )
|
|
|
|
DUP 9 > IF 2DROP 0 EXIT THEN ( bad )
|
2020-04-01 06:04:28 +11:00
|
|
|
( good, add to running result )
|
2020-04-09 22:23:53 +10:00
|
|
|
SWAP 10 * + ( a r*10+n )
|
|
|
|
SWAP 1 + SWAP ( a+1 r )
|
2020-04-01 06:04:28 +11:00
|
|
|
( read next char )
|
2020-04-09 22:23:53 +10:00
|
|
|
OVER C@
|
|
|
|
DUP NOT UNTIL
|
2020-04-01 06:04:28 +11:00
|
|
|
( we're done and it's a success. We have "a r c", we want
|
|
|
|
"r 1". )
|
2020-04-09 22:23:53 +10:00
|
|
|
DROP SWAP DROP 1
|
2020-04-01 06:04:28 +11:00
|
|
|
;
|
|
|
|
|
2020-03-28 02:49:50 +11:00
|
|
|
( This is only the "early parser" in earlier stages. No need
|
|
|
|
for an abort message )
|
|
|
|
: (parse)
|
2020-04-09 22:23:53 +10:00
|
|
|
(parsed) NOT IF ABORT THEN
|
2020-03-28 02:49:50 +11:00
|
|
|
;
|
|
|
|
|
2020-03-30 23:37:33 +11:00
|
|
|
: C<
|
2020-04-03 00:58:02 +11:00
|
|
|
( 0c == CINPTR )
|
2020-04-09 22:23:53 +10:00
|
|
|
0x0c RAM+ @ EXECUTE
|
2020-03-30 23:37:33 +11:00
|
|
|
;
|
|
|
|
|
2020-04-01 06:26:43 +11:00
|
|
|
: ,
|
2020-04-09 22:23:53 +10:00
|
|
|
HERE @ !
|
|
|
|
HERE @ 2 + HERE !
|
2020-04-01 06:26:43 +11:00
|
|
|
;
|
|
|
|
|
2020-03-28 10:12:46 +11:00
|
|
|
: C,
|
2020-04-09 22:23:53 +10:00
|
|
|
HERE @ C!
|
|
|
|
HERE @ 1 + HERE !
|
2020-03-28 10:12:46 +11:00
|
|
|
;
|
|
|
|
|
2020-03-29 04:18:43 +11: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-04-09 22:23:53 +10:00
|
|
|
: WS? 33 CMP 1 + NOT ;
|
2020-03-29 04:18:43 +11:00
|
|
|
|
2020-03-29 04:02:04 +11:00
|
|
|
: TOWORD
|
|
|
|
BEGIN
|
2020-04-09 22:23:53 +10:00
|
|
|
C< DUP WS? NOT IF EXIT THEN DROP
|
2020-03-29 04:02:04 +11:00
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
2020-03-29 03:55:22 +11:00
|
|
|
( Read word from C<, copy to WORDBUF, null-terminate, and
|
|
|
|
return, make HL point to WORDBUF. )
|
|
|
|
: WORD
|
2020-04-03 00:58:02 +11:00
|
|
|
( 0e == WORDBUF )
|
2020-04-09 22:23:53 +10:00
|
|
|
0x0e RAM+ ( a )
|
|
|
|
TOWORD ( a c )
|
2020-03-29 03:55:22 +11:00
|
|
|
BEGIN
|
|
|
|
( We take advantage of the fact that char MSB is
|
|
|
|
always zero to pre-write our null-termination )
|
2020-04-09 22:23:53 +10:00
|
|
|
OVER ! ( a )
|
|
|
|
1 + ( a+1 )
|
|
|
|
C< ( a c )
|
|
|
|
DUP WS?
|
2020-03-29 03:55:22 +11:00
|
|
|
UNTIL
|
|
|
|
( a this point, PS is: a WS )
|
|
|
|
( null-termination is already written )
|
2020-04-09 22:23:53 +10:00
|
|
|
2DROP
|
|
|
|
0x0e RAM+
|
2020-03-29 03:55:22 +11:00
|
|
|
;
|
|
|
|
|
2020-04-09 06:12:34 +10:00
|
|
|
: SCPY
|
|
|
|
BEGIN ( a )
|
2020-04-09 22:23:53 +10:00
|
|
|
DUP C@ ( a c )
|
|
|
|
DUP C, ( a c )
|
|
|
|
NOT IF DROP EXIT THEN
|
|
|
|
1 + ( a+1 )
|
2020-04-09 06:12:34 +10:00
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
2020-03-28 07:52:42 +11:00
|
|
|
: (entry)
|
2020-04-09 22:23:53 +10:00
|
|
|
HERE @ ( h )
|
|
|
|
WORD ( h s )
|
|
|
|
SCPY ( h )
|
2020-03-28 07:52:42 +11:00
|
|
|
( Adjust HERE -1 because SCPY copies the null )
|
2020-04-09 22:23:53 +10:00
|
|
|
HERE @ 1 - ( h h' )
|
|
|
|
DUP HERE ! ( h h' )
|
|
|
|
SWAP - ( sz )
|
2020-03-28 07:52:42 +11:00
|
|
|
( write prev value )
|
2020-04-09 22:23:53 +10:00
|
|
|
HERE @ CURRENT @ - ,
|
2020-03-28 07:52:42 +11:00
|
|
|
( write size )
|
2020-04-09 22:23:53 +10:00
|
|
|
C,
|
|
|
|
HERE @ CURRENT !
|
2020-03-28 07:52:42 +11:00
|
|
|
;
|
|
|
|
|
2020-03-29 03:55:22 +11:00
|
|
|
: INTERPRET
|
|
|
|
BEGIN
|
2020-04-09 22:23:53 +10:00
|
|
|
WORD
|
|
|
|
(find)
|
2020-03-29 03:55:22 +11:00
|
|
|
IF
|
2020-04-09 22:23:53 +10:00
|
|
|
1 FLAGS !
|
2020-03-29 03:55:22 +11:00
|
|
|
EXECUTE
|
2020-04-09 22:23:53 +10:00
|
|
|
0 FLAGS !
|
2020-03-29 03:55:22 +11:00
|
|
|
ELSE
|
2020-04-09 22:23:53 +10:00
|
|
|
(parse*) @ EXECUTE
|
2020-03-29 03:55:22 +11:00
|
|
|
THEN
|
|
|
|
AGAIN
|
|
|
|
;
|
|
|
|
|
2020-04-03 23:31:30 +11:00
|
|
|
( system c< simply reads source from binary, starting at
|
|
|
|
LATEST. Convenient way to bootstrap a new system. )
|
|
|
|
: (c<)
|
2020-04-08 07:32:04 +10:00
|
|
|
( 60 == SYSTEM SCRATCHPAD )
|
2020-04-09 22:23:53 +10:00
|
|
|
0x60 RAM+ @ ( a )
|
|
|
|
DUP C@ ( a c )
|
|
|
|
SWAP 1 + ( c a+1 )
|
|
|
|
0x60 RAM+ ! ( c )
|
2020-04-03 23:31:30 +11:00
|
|
|
;
|
|
|
|
|
2020-03-29 03:55:22 +11:00
|
|
|
: BOOT
|
2020-04-09 22:23:53 +10:00
|
|
|
LIT< (parse) (find) DROP (parse*) !
|
2020-04-08 07:32:04 +10:00
|
|
|
( 60 == SYSTEM SCRATCHPAD )
|
2020-04-09 22:23:53 +10:00
|
|
|
CURRENT @ 0x60 RAM+ !
|
2020-04-03 00:58:02 +11:00
|
|
|
( 0c == CINPTR )
|
2020-04-09 22:23:53 +10:00
|
|
|
LIT< (c<) (find) DROP 0x0c RAM+ !
|
|
|
|
LIT< INIT (find)
|
2020-04-03 14:21:53 +11:00
|
|
|
IF EXECUTE
|
2020-04-09 22:23:53 +10:00
|
|
|
ELSE DROP INTERPRET THEN
|
2020-03-29 03:55:22 +11:00
|
|
|
;
|
|
|
|
|
2020-03-31 04:50:53 +11:00
|
|
|
( LITN has to be defined after the last immediate usage of
|
|
|
|
it to avoid bootstrapping issues )
|
|
|
|
: LITN
|
2020-03-31 08:05:00 +11:00
|
|
|
( 32 == NUMBER )
|
2020-04-09 22:23:53 +10:00
|
|
|
32 , ,
|
2020-03-31 04:50:53 +11:00
|
|
|
;
|
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
: IMMED? 1 - C@ 0x80 AND ;
|
2020-04-09 10:09:32 +10:00
|
|
|
|
2020-03-28 07:16:57 +11:00
|
|
|
( : and ; have to be defined last because it can't be
|
|
|
|
executed now also, they can't have their real name
|
2020-04-09 06:23:02 +10:00
|
|
|
right away.
|
2020-04-04 23:40:55 +11:00
|
|
|
)
|
2020-03-28 07:16:57 +11:00
|
|
|
|
|
|
|
: X
|
2020-04-09 22:23:53 +10:00
|
|
|
(entry)
|
2020-03-29 01:38:05 +11:00
|
|
|
( We cannot use LITN as IMMEDIATE because of bootstrapping
|
2020-04-01 12:46:52 +11:00
|
|
|
issues. Same thing for ",".
|
|
|
|
32 == NUMBER 14 == compiledWord )
|
2020-04-09 23:21:55 +10:00
|
|
|
[ 32 H@ ! 2 ALLOT 14 H@ ! 2 ALLOT ] ,
|
2020-03-28 07:16:57 +11:00
|
|
|
BEGIN
|
2020-04-09 22:23:53 +10:00
|
|
|
WORD
|
|
|
|
(find)
|
2020-03-28 07:16:57 +11:00
|
|
|
( is word )
|
2020-04-09 22:23:53 +10:00
|
|
|
IF DUP IMMED? IF EXECUTE ELSE , THEN
|
2020-03-28 07:16:57 +11:00
|
|
|
( maybe number )
|
2020-04-09 22:23:53 +10:00
|
|
|
ELSE (parse*) @ EXECUTE LITN THEN
|
2020-03-28 07:16:57 +11:00
|
|
|
AGAIN
|
2020-04-09 06:23:02 +10:00
|
|
|
; IMMEDIATE
|
2020-03-28 07:16:57 +11:00
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
XCURRENT @ ( to PSP )
|
|
|
|
|
2020-03-28 07:16:57 +11:00
|
|
|
: Y
|
2020-04-09 22:23:53 +10:00
|
|
|
['] EXIT ,
|
|
|
|
R> DROP ( exit : )
|
2020-04-09 06:23:02 +10:00
|
|
|
; IMMEDIATE
|
2020-03-28 02:27:40 +11:00
|
|
|
|
2020-04-09 06:23:02 +10:00
|
|
|
( Give ":" and ";" their real name )
|
2020-04-09 23:21:55 +10:00
|
|
|
';' XCURRENT @ 4 - C!
|
|
|
|
':' SWAP ( from PSP ) 4 - C!
|
2020-04-03 02:29:23 +11:00
|
|
|
|
2020-04-09 22:23:53 +10:00
|
|
|
(xentry) _
|
|
|
|
H@ 256 /MOD 2 PC! 2 PC!
|