variable temp \ first variable
: swap >r temp! r> temp@ ;
: over >r temp! temp@ r> temp@ ;
: rot >r swap r> swap ;
: dup temp! temp@ temp@ ;
: 2drop + drop ;
: 2dup over over ;
\ note: must preserve return address!
: r@ r> r> temp! temp@ >r temp@ swap >r ;
: r! r> r> drop swap >r >r ;
: invert -1 nand ;
: negate invert 1 + ;
: - negate + ;
: 1+ 1 + ;
: 1- -1 + ;
: +! dup >r @ + r> ! ;
: 0= if 0 else -1 then ;
: 0<> if -1 else 0 then ;
: = - 0= ;
: <> = 0= ;
: == - 0= ;
: or invert swap invert nand ;
: xor 2dup nand 1+ dup + + + ;
: and nand invert ;
\ pop off the return address, then limit, then index.
\ add one to index and push limit and index back to stack; then compare
\ increased index with limit. return true if equal
: loopimpl r> r> r> 1+ 2dup >r >r = swap >r ;
\ same thing but accepts input argument saying countdown value
: -loopimpl r> swap r> swap r> swap - 2dup >r >r = swap >r ;
\ note: must preserve return address!
: i r> r> r> temp! temp@ >r >r >r temp@ ;
: j r> r> r> r> r> temp! temp@ >r >r >r >r >r temp@ ;
: cells dup + ;
: cell+ 1 cells + ;
: * >r 0 r> 0 do over + loop swap drop ;
: 2* 2 * ;
: 0< $8000 nand invert if -1 else 0 then ;
: % ( value divisor -- modulus ) begin 2dup - dup 0< if + -1 else rot drop swap 0 then until swap drop ;
: type ( c-addr u -- )
0 do
dup i + c@ emit
loop
drop
;
: cr $0D emit $0A emit ;
: 0>= $8000 nand invert if 0 else -1 then ;
: 0<= ( n -- f ) dup 0= swap 0< or ;
: -rot ( w1 w2 w3 -- w3 w1 w2 ) swap >r swap r> ;
: tuck ( w1 w2 -- w2 w1 w2 ) swap over ;
: throw 0 = if else abort then ;
: ?dup ( w -- 0 | w w ) dup 0= if else dup then ;
: 2over ( w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2 )
rot >r rot dup r> swap >r >r -rot r@ -rot r> r> swap ;
: 2swap ( w1 w2 w3 w4 -- w3 w4 w1 w2 )
rot >r rot r> ;
\ TODO involve "cells"
: 2@ ( a-addr -- w1 w2 ) dup 1+ @ swap @ ;
: 2! ( w1 w2 a-addr -- ) dup temp! ! temp@ 1+ ! ;
: nip >r temp! r> ;
: < 2dup xor 0< if drop 0< else - 0< then ;
: u< 2dup xor 0< if nip 0< else - 0< then ;
: > swap < ;
: u> swap u> ;
: >= 2dup > >r = r> or ;
: within ( u1 u2 u3 -- flag ) over - >r - r> u< ;
: throw 0 = if else abort then ;
: true -1 ;
: false 0 ;
: roll ( x .. n -- .. x )
dup
begin dup 0 <> while 1- rot >r repeat \ top of alt is counter
drop
begin dup 0 <> while 1- r> -rot repeat \ top of alt is counter
drop
;
: pick ( x .. n -- x .. x )
dup
begin dup 0 <> while 1- rot >r repeat \ top of alt is counter
drop
over
swap
begin dup 0 <> while 1- r> -rot repeat \ top of alt is counter
drop
;
\ hardcoded *roll and *pick variants that are optimizable w/o inline
: 3roll
>r >r
swap r> swap r> swap
;
: 4roll
>r >r >r
swap r> swap r> swap r> swap
;
: compare ( c-addr1 u1 c-addr2 u2 -- n )
begin
rot
2dup
or 0= if
drop 0 1
else ( c-addr1 c-addr2)
dup 0= if
drop -1 1
else
over 0= if
drop 1 1
else ( c-addr1 c-addr2 u2 u1 )
>r >r ( c-addr1 c-addr2 )
2dup c@ swap c@ ( c-addr1 c-addr2 c2 c1 )
- ( c-addr1 c-addr2 [c2 - c1] )
dup 0< if
\ less than 1
drop
r> r>
drop 1 1
else if
\ more than 1
r> r>
drop -1 1
else
\ loop
1+ swap 1+ swap
r> 1- r> 1-
rot rot
0 ( continue )
then
then
then
then
then
until
swap drop
swap drop
swap drop
;