home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.whtech.com
/
ftp.whtech.com.7z
/
ftp.whtech.com
/
emulators
/
v9t9
/
linux
/
sources
/
V9t9
/
tools
/
Forth
/
kernel.fs
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS
UTF-8
Wrap
FORTH Source
|
2006-10-19
|
15.9 KB
|
1,226 lines
\
\ Kernel
\
\
\ Core words
\
\ Core words. If primitives have been defined, these are not used.
\ ! # #> #S ' ( * */ */MOD + +! +LOOP , - . ." / /MOD
\ 0< 0= 1+ 1- 2! 2* 2/ 2@ 2drop 2dup 2over 2swap :
\ ; < <# = > >body >in >number >r ?dup @ abort abort"
\ abs accept align aligned allot and base begin bl c! c,
\ c@ cell+ cells char char+ chars constant count cr create
\ decimal depth do does> drop dup else emit environment?
\ evaluate execute exit fill find fm/mod here hold i if
\ immediate invert j key leave literal loop lshift m* max min
\ mod move negate or over postpone quit r> r@ recurse
\ repeat rot rshift s" s>d sign source space spaces state
\ swap then type u. u< um* um/mod unloop until variable
\ while word xor [ ['] [char] ]
\ stack words
[IFUNDEF] 2DROP
: 2DROP \ core
drop drop
;
[THEN]
test" 2drop 2. 3. 2drop 2. d="
[IFUNDEF] 2DUP
: 2DUP \ core
over over
;
[THEN]
test" 2dup 1. 2. 2dup 2. d="
[IFUNDEF] 2OVER
: 2OVER
2 pick 2 pick
;
[THEN]
test" 2over 1. 2. 2over 1. d= "
[IFUNDEF] 2SWAP
: 2SWAP
rot >r rot r>
;
[THEN]
[IFUNDEF] >R
\ : >R
\ ;
[THEN]
[IFUNDEF] ?DUP
: ?DUP
dup if dup then
;
[THEN]
[IFUNDEF] DEPTH
: DEPTH
sp@ sp0 @ - negate [ cell<< ] literal rshift
;
[THEN]
[IFUNDEF] DROP
: DROP
>r rdrop
;
[THEN]
[IFUNDEF] DUP
: DUP
>r r@ r>
;
[THEN]
[IFUNDEF] OVER
: OVER
2>r r@ 2r> swap
;
[THEN]
test" over 1 2 over 1 = swap 2 = and swap 1 = and"
[IFUNDEF] TUCK
: TUCK swap over ;
[THEN]
[IFUNDEF] R>
\ : R>
\ ;
error" need prim r>"
[THEN]
[IFUNDEF] R@
: R@
r> dup >r
;
[THEN]
[IFUNDEF] SWAP
\ : SWAP
\ ;
error" need prim swap"
[THEN]
\ memory words
[IFUNDEF] !
\ : !
\ ;
error" need prim !"
[THEN]
[IFUNDEF] +!
: +!
dup @ over + swap !
;
[THEN]
[IFUNDEF] 2!
: 2!
2dup ! cell+ !
;
[THEN]
[IFUNDEF] 2@
: 2@
dup cell+ @ swap @
;
[THEN]
[IFUNDEF] @
\ : @
\ ;
error" need prim @"
[THEN]
[IFUNDEF] C!
\ : C!
\ ;
error" need prim c!"
[THEN]
[IFUNDEF] C@
\ : C@
\ ;
error" need prim c@"
[THEN]
[IFUNDEF] CHAR+
: CHAR+
#char +
;
[THEN]
[IFUNDEF] CHARS
: CHARS
#char *
;
[THEN]
[IFUNDEF] CELL+
: CELL+
#cell +
;
[THEN]
[IFUNDEF] CELLS
: CELLS
#cell *
;
[THEN]
[IFUNDEF] FILL
: FILL
rot rot
over + swap
?do dup I c! loop drop
;
[THEN]
[IFUNDEF] MOVE
\ note: chars == address units
: MOVE
>r 2dup u< if r> cmove> else r> cmove then
;
[THEN]
\ math words
[IFUNDEF] *
: *
um* d>s
;
[THEN]
[IFUNDEF] */
: */
*/mod swap drop
;
[THEN]
[IFUNDEF] */MOD
: */MOD ( n1 n2 n3 -- n4 n5 ) \ core star-slash-mod
>r m* r> sm/rem
;
[THEN]
[IFUNDEF] +
\ : +
\ ;
error" need prim +"
[THEN]
[IFUNDEF] -
: -
negate +
;
[THEN]
[IFUNDEF] /
: /
/mod swap drop
;
[THEN]
[IFUNDEF] /MOD
: /MOD
>r s>d r> sm/rem
;
[THEN]
[IFUNDEF] 0<
\ : 0<
\ ;
[THEN]
[IFUNDEF] 0=
: 0=
if 0 else -1 then
;
[THEN]
[IFUNDEF] 1+
: 1+
1 +
;
[THEN]
[IFUNDEF] 1-
: 1-
1 -
;
[THEN]
[IFUNDEF] 2*
: 2*
dup +
;
[THEN]
[IFUNDEF] 2/
: 2/
1 rshift
;
[THEN]
[IFUNDEF] <
: <
- 0<
;
[THEN]
[IFUNDEF] =
: =
- 0=
;
[THEN]
[IFUNDEF] >
: >
- 0>
;
[THEN]
[IFUNDEF] ABS
: ABS
dup 0< if negate then
;
[THEN]
[IFUNDEF] AND
\ : AND
\ ;
[THEN]
[IFUNDEF] FM/MOD
: FM/MOD \ d1 n1 -- n2 n3 core f_m_slash_mod
\ floored division: d1 = n3*n1+n2, 0<=n2<n1 or n1<n2<=0
dup >r dup 0< IF negate >r dnegate r> THEN
over 0< IF tuck + swap THEN
um/mod
r> 0< IF swap negate swap THEN
;
[THEN]
test" fm/mod 1ff. f fm/mod 22 = swap 1 = and"
test" fm/mod -1ff. f fm/mod -23 = swap e = and"
[IFUNDEF] INVERT
: INVERT
negate 1-
;
[THEN]
[IFUNDEF] LSHIFT
: LSHIFT
0 ?do dup + loop
;
[THEN]
\ [IFUNDEF] M*
: M*
2dup xor >r
abs swap abs
um*
r> 0< if dnegate then
;
\ [THEN]
test" m* 3 -4 m* -$c. d="
test" m* -4 -3 m* $c. d="
[IFUNDEF] MAX
: MAX
2dup >= if drop else nip then
;
[THEN]
test" max -5 6 max 6 ="
[IFUNDEF] MIN
: MIN
2dup <= if drop else nip then
;
[THEN]
test" min 6 -5 min -5 ="
[IFUNDEF] MOD
: MOD
/mod drop
;
[THEN]
[IFUNDEF] NEGATE
: NEGATE
invert 1+
;
[THEN]
[IFUNDEF] OR
\ : OR
\ ;
[THEN]
[IFUNDEF] ROT
: ROT \ a b c -- b c a
>r swap r> swap
;
[THEN]
test" rot 1 2 3 rot 1 = swap 3 = and swap 2 ="
[IFUNDEF] RSHIFT
: RSHIFT
0 ?do 2/ loop
;
[THEN]
[IFUNDEF] S>D
\ both endians will have the high word on top
: S>D
dup 0< if -1 else 0 then
;
[THEN]
test" s>d 45 s>d 0= swap 45 = and"
[IFUNDEF] SM/REM
: SM/REM ( d1 n1 -- n2 n3 )
\ symmetric division: d1 = n3*n1+n2, sign(n2)=sign(d1) or 0
over >r
dup >r abs
rot rot
dabs rot um/mod
r> r@ xor 0< IF negate THEN
r> 0< IF swap negate swap THEN
;
[THEN]
test" sm/rem -$1ff. $f sm/rem -$22 = swap -$1 = and"
[IFUNDEF] U<
\ : U<
\ ;
error" need prim u<"
[THEN]
test" u< 1 2 u<"
test" u< 2 1 u< 0="
test" u< -1 2 u< 0="
test" u< 2 -1 u<"
[IFUNDEF] UM*
\ magic code stolen from gforth
\
: d2*+ ( ud n -- ud+n c )
over MINI
and >r >r 2dup d+ swap r> + swap r>
;
: UM*
>r >r 0 0 r> r> [ 8 cells ] literal 0
DO
over >r dup >r 0< and d2*+ drop
r> 2* r> swap
LOOP 2drop
;
[THEN]
[IFUNDEF] UM/MOD
\ magic code stolen from gforth
\
: /modstep ( ud c R: u -- ud-?u c R: u )
>r over r@ u< 0= or IF r@ - 1 ELSE 0 THEN d2*+ r>
;
: UM/MOD \ ud u1 -- u2 u3 core u_m_slash_mod
0 swap [ 8 cells 1 + ] literal 0
?DO /modstep
LOOP drop swap 1 rshift or swap
;
[THEN]
[IFUNDEF] XOR
\ : XOR
\ ;
error" need prim xor"
[THEN]
[IFUNDEF] TYPE
: TYPE ( caddr n -- )
0 ?do
dup c@ emit 1+
loop
drop
;
[THEN]
[IFUNDEF] ."
: ."
postpone s"
state @ if
[compile] type
else
type
then
; immediate
[THEN]
[IFUNDEF] >NUMBER
: dn* ( ud un -- ud )
\ hi.lo
\ * n
\ -------------
\ hi.lo*n lo.lo*n
\ lo.hi*n 0
dup rot \ ( lo-d un un hi-d )
um* \ ( lo-d un d.hiprod )
drop >r \ save lo.hi*n
um* \ ( d.loprod )
0 r> \ create d.hiprod
d+
;
: (skip)
1 /string
;
\ yes, this ignores '+' and '-' and '.'
: >NUMBER \ CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
begin \ ( ud1 c-addr1 u1 )
dup \ chars left?
if
over c@
base @
swap digit \ legal digit?
else
0
then \ ( ud1 c-addr1 u1 # -1 | ud1 c-addr1 u1 0 )
while
>r \ save digit
2swap \ get accum
base @ dn*
r> s>d d+ \ add digit
2swap
(skip) \ advance pointer
\ 2dup . .
repeat
;
[THEN]
\ : testnum s" 18446744069414584320" ;
\ test" >number 0. testnum >number 2drop 2dup d. 1. d+ or 0="
: testnum s" 4294967295" ;
test" >number 0. testnum >number 2drop 2dup d. 1. d+ or 0="
[IFUNDEF] ABORT"
: (abort")
rot if cr ." error: " type cr abort else 2drop then
;
: ABORT"
\ Compilation: ( "ccc<quote>" -- )
\
\ Parse ccc delimited by a " (double-quote). Append the run-time semantics
\ given below to the current definition.
\
\ Run-time: ( i*x x1 -- | i*x ) ( R: j*x -- | j*x )
\
\ Remove x1 from the stack. If any bit of x1 is not zero, display ccc and
\ perform an implementation-defined abort sequence that includes the
\ function of ABORT.
postpone s"
state @ if
[compile] (abort")
else
(abort")
then
; immediate
[THEN]
[IFUNDEF] BASE
User BASE
[THEN]
[IFUNDEF] EXECUTE
\ : EXECUTE
\ ;
error" need prim execute"
[THEN]
\ \\\\\\\\\\\\\\\
[IFUNDEF] ]
: ]
-1 state !
;
[THEN]
[IFUNDEF] I
\ : I
\ ;
[THEN]
[IFUNDEF] J
\ : J
\ ;
[THEN]
[IFUNDEF] LITERAL
: DLITERAL
state @ if
swap postpone lit , postpone lit ,
then
; immediate
: LITERAL
state @ if
postpone lit ,
then
; immediate
[THEN]
[IFUNDEF] SLITERAL
: string, ( caddr u -- )
dup c,
here swap chars dup allot move
;
: SLITERAL \ C: ( caddr u -- ) R: ( -- caddr u )
state @ if
[compile] (s") string, align
else
\ copy string to safe place
>r (slit-pad) @ r@ cmove
(slit-pad) @ r>
then
; immediate
[THEN]
[IFUNDEF] S"
: S"
$22 parse
postpone sliteral
; immediate
[THEN]
[IFUNDEF] VARIABLE
\ : VARIABLE
\ ;
[THEN]
\ printing words
user hld \ offset into number pad
[IFUNDEF] -pad
: -pad
(#-pad) @
;
[THEN]
\ we use an area at the end of dictionary in front of PAD
[IFUNDEF] <#
: <# \ ( -- )
\ Initialize the pictured numeric output conversion process.
-pad hld !
;
[THEN]
[IFUNDEF] HOLD
: HOLD \ ( char -- )
\ Add char to the beginning of the pictured numeric output string. An ambiguous condition exists if HOLD executes outside of
\ a <# #> delimited number conversion.
-1 hld +!
hld @ c!
;
[IFUNDEF] #
[IFUNDEF] M/MOD
: M/MOD ( ud un -- ur udq )
\ divide high word by base
>r 0 r@ ( ud.l ud.h:0 un | R: un )
u/ ( ud. ud.h*10000%r:ud.h*10000/r | R: un )
r> swap >r ( ud.l:ud.h*10000%r un | R: ud.h*10000/r )
u/ ( r q )
r> ( r q ud.h*10000/r )
;
[THEN]
[IFUNDEF] (#)
: (#) ( ud base -- ud' ch )
m/mod \ ( ur udq )
rot \ ( udq ur )
$09 over < \ ( udq 9<ur )
if $07 + then
$30 +
;
[THEN]
: # \ ( ud1 -- ud2 )
\ Divide ud1 by the number in BASE giving the quotient ud2 and the remainder n. (n is the least-significant digit of ud1.)
\ Convert n to external form and add the resulting character to the beginning of the pictured numeric output string. An
\ ambiguous condition exists if # executes outside of a <# #> delimited number conversion.
base @
(#)
hold
;
[THEN]
[IFUNDEF] #>
: #> \ ( xd -- c-addr u )
\ Drop xd. Make the pictured numeric output string available as a character string. c-addr and u specify the resulting
\ character string. A program may replace characters within the string.
2drop hld @ -pad over -
;
[THEN]
[IFUNDEF] #S
: #S \ ( ud1 -- ud2 )
\ Convert one digit of ud1 according to the rule for #. Continue conversion until the quotient is zero. ud2 is zero. An
\ ambiguous condition exists if #S executes outside of a <# #> delimited number conversion.
begin
#
2dup or 0=
until
;
[THEN]
test" abs 394 abs 394 ="
test" abs -395 abs 395 ="
[IFUNDEF] .
: .
0 .r space
;
[THEN]
test" . -640 . 1"
[IFUNDEF] BL
$20 constant BL
[THEN]
[IFUNDEF] CR
: CR
$0D emit
;
[THEN]
[IFUNDEF] DECIMAL
: DECIMAL
$A base !
;
[THEN]
[IFUNDEF] SIGN
: SIGN \ ( n -- ) \ depends on high word being TOS
0< if
$2d hold
then
;
[THEN]
[IFUNDEF] SPACE
: SPACE
bl emit
;
[THEN]
[IFUNDEF] SPACES
: SPACES
0 max 0 ?do bl emit loop
;
[THEN]
[IFUNDEF] U.
: U.
0 u.r space
;
[THEN]
\ string words
[IFUNDEF] COUNT
: COUNT
dup c@ swap 1+ swap
;
[THEN]
[IFUNDEF] WORD
: (parse-word) ( ch -- caddr u )
(skip-spaces)
parse \ get new word
;
: WORD \ ( char "<chars>ccc<char>" -- c-addr )
(parse-word)
2dup + bl swap c! \ word ends with space
-pad (>c) \ copy to word pad
-pad \ leave addr
;
[THEN]
\ I/O words
[IFUNDEF] ACCEPT
: overstrike
bksp emit bl emit bksp emit
;
: ACCEPT
\ ( c-addr +n1 -- +n2 )
\ Receive a string of at most +n1 characters. An ambiguous condition exists if +n1 is zero or greater than 32,767. Display
\ graphic characters as they are received. A program that depends on the presence or absence of non-graphic characters in
\ the string has an environmental dependency. The editing functions, if any, that the system performs in order to construct
\ the string are implementation-defined.
\
\ (EJS: this one does not automatically abort at n1 chars.)
swap >r \ store c-addr on R:
0 \ position
begin
key
dup $0d <>
while
dup bksp <>
if
>r \ store key
2dup <= if bksp emit then
r@ emit \ show key
over 1- min \ get proper index ( max idx -- )
dup r> swap r@ + c! \ write
1+
else
drop dup 0 > if \ don't go too far
overstrike \ backspace
1-
then
then
repeat
drop \ key
min \ lose max #chars
rdrop
;
\ : prompt ." type stuff> " ;
\ test" accept prompt pad 5 accept pad swap $2a emit type $2a emit 1"
[THEN]
[IFUNDEF] EMIT
\ : EMIT
\ drop
\ ;
error" need emit"
[THEN]
[IFUNDEF] ENVIRONMENT?
: ENVIRONMENT?
2drop 0
;
[THEN]
[IFUNDEF] KEY
\ : KEY
\ ;
error" need key"
[THEN]
: (quit?)
dup &81 = swap &113 = or
;
: (pause?) ( -- <t|f to quit> )
key? dup if
key (quit?) 0= if \ 'q'
0= key (quit?) or
then
then
;
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ CORE EXT words
\ #tib .( .r 0<> 0> 2>r 2r> 2r@
\ :noname <> ?do again c" case compile,
\ convert endcase endof erase expect
\ false hex marker nip of pad parse
\ pick query refill restore-input roll
\ save-input source-id span tib to
\ true tuck u.r u> unused value
\ within [compile] \
[IFUNDEF] #TIB
User #TIB
[THEN]
[IFUNDEF] .(
\ : .(
\ ;
[THEN]
[IFUNDEF] .R
\ : .R
\ ;
[THEN]
[IFUNDEF] 0<>
\ : 0<>
\ ;
[THEN]
[IFUNDEF] 0>
\ : 0>
\ ;
[THEN]
[IFUNDEF] 2>R
\ : 2>R
\ ;
[THEN]
[IFUNDEF] 2R>
\ : 2R>
\ ;
[THEN]
[IFUNDEF] 2R@
\ : 2R@
\ ;
[THEN]
[IFUNDEF] :NONAME
\ : :NONAME
\ ;
[THEN]
[IFUNDEF] <>
: <> \ core ext
= NOT
;
[THEN]
[IFUNDEF] .R
: .R
>r \ field width
s>d \ make double
dup >r \ sign
dabs <# #S r> sign #>
r> over - spaces
type
;
[THEN]
[IFUNDEF] C"
\ : C"
\ ;
[THEN]
[IFUNDEF] CONVERT
\ : CONVERT
\ ;
[THEN]
[IFUNDEF] ERASE
\ : ERASE
\ ;
[THEN]
[IFUNDEF] EXPECT
\ : EXPECT
\ ;
[THEN]
[IFUNDEF] FALSE
0 constant FALSE
[THEN]
[IFUNDEF] HEX
: HEX
$10 base !
;
[THEN]
[IFUNDEF] MARKER
\ : MARKER
\ ;
[THEN]
[IFUNDEF] NIP
\ : NIP
\ ;
[THEN]
[IFUNDEF] PAD
: PAD
(pad) @
;
[THEN]
[IFUNDEF] PARSE \ core ext, used to implement WORD
\ Match 'char' inside [caddr..caddr+u) and return length of word
: (match) ( caddr u char "ccc<char>" -- u )
over >r \ save original #chars
>r \ store char
begin
dup \ any more chars left?
if
over c@ \ ( caddr u ch' )
r@ \ ( caddr u ch' ch )
<> \ ( caddr u t/f )
else
0
then
while
1- swap 1+ swap
repeat
rdrop
swap drop ( u' )
r> ( u' u )
swap - ( len )
;
[THEN]
: mystr s" 1111123456" ;
test" (match) mystr $32 (match) mystr drop swap type 1"
\ Return bounds of remaining source
: (src>) ( -- caddr u )
source
>in @
- 0 max
swap >in @ + swap
;
\ (>src) advances >in by u' bytes
: (>src) \ ( u' -- )
1+ >in +! \ update >in
;
: PARSE \ ( char "ccc<char>" -- c-addr u )
\ Parse ccc delimited by the delimiter char.
\ c-addr is the address (within the input buffer) and u is the length of the parsed string. If the parse area was empty, the
\ resulting string has a zero length.
(src>) over >r
rot (match)
dup (>src)
r> swap
;
\ Skip spaces in source
: (skip-spaces) ( -- )
(src>)
0 ?do
dup c@ bl > if
\ unloop drop exit \ needed to avoid problem using cross.fs's 'leave'
unloop leave \ nope, UNLOOP doesn't exit the loop.
else
1+ 1 >in +!
then
loop
drop
;
[THEN]
[IFUNDEF] PICK
\ : PICK
\ ;
[THEN]
[IFUNDEF] ROLL
\ : ROLL
\ ;
[THEN]
[IFUNDEF] SPAN
\ : SPAN
\ ;
[THEN]
[IFUNDEF] TO
\ : TO
\ ;
[THEN]
[IFUNDEF] TRUE
-1 constant TRUE
[THEN]
[IFUNDEF] TUCK
: TUCK
dup >r swap r>
;
[THEN]
[IFUNDEF] U.R
: U.R
>r
0 \ make double
<# #S #>
r> over - spaces
type
;
[THEN]
[IFUNDEF] U>
\ : U>
\ ;
[THEN]
[IFUNDEF] UNUSED
\ : UNUSED
\ ;
[THEN]
[IFUNDEF] VALUE
\ : VALUE
\ ;
[THEN]
[IFUNDEF] WITHIN
: WITHIN ( test low high -- flag )
over - >r - r> u<
;
[THEN]
[IFUNDEF] \
: \
blk @
if >in @ c/l / 1+ c/l * >in ! exit
then
source >in ! drop
; immediate
[THEN]
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\
\ STRING words
\
[IFUNDEF] CMOVE
\ : CMOVE
\ ;
[THEN]
[IFUNDEF] CMOVE>
\ : CMOVE>
\ ;
[THEN]
[IFUNDEF] /STRING
\ : /STRING
\ ;
[THEN]
[IFUNDEF] COMPARE
\ : COMPARE
\ ;
[THEN]
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\
\ Double words
\
[IFUNDEF] D.
: D.R
>r \ field width
dup >r \ sign
dabs <# #S r> sign #>
r> over - spaces
type
;
: D. \ DOUBLE
0 d.r space
;
[THEN]
[IFUNDEF] UD.
: UD.R \ double
>r
<# #S #>
r> over - spaces
type
;
: UD. \ double
0 UD.R
space
;
[THEN]
[IFUNDEF] D-
: D-
DNEGATE D+
;
[THEN]
[IFUNDEF] D<
: D<
D- D0<
;
[THEN]
test" d< 20. 40. d<"
test" d< 50. 40. d< 0="
test" d< -20. -10. d<"
test" d< -10. -20. d< 0="
test" d< -10. 10. d<"
test" d< 10. -10. d< 0="
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ BLOCKS
[IFUNDEF] BLK
User BLK
[THEN]
[IFUNDEF] C/L
32 constant C/L
[THEN]
[IFUNDEF] CHARS/BLOCK
1024 constant CHARS/BLOCK
[THEN]
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\
\ TOOLS words
\
[IFUNDEF] .S
: .S
." <" depth dup 0 u.r [char] : emit 0 ?do
depth i - 1- pick u.
loop ." >"
;
[THEN]
[IFUNDEF] ?
: ? @ . ;
[THEN]
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\