~vdupras/duskos

f241047d16257e9b9da60c11b9858dee881fe86c — Virgil Dupras a month ago e1b8282
Add 1+! 1-! to1+ to1-

I've been hesitating on those ones for quite a while now, wondering if they were
worth their weight, but the stack juggling that the regular "to+" brought in the
new DuskCC code was enough to tip the balance. So here they are.
M fs/asm/i386.fs => fs/asm/i386.fs +4 -4
@@ 54,14 54,14 @@
\ ability", so we have a rolling bank of 16 numbers down below.
create _bank $10 CELLSZ * allot
0 value _bankidx
: newbankid 1 to+ _bankidx _bankidx $f and ;
: newbankid to1+ _bankidx _bankidx $f and ;
: bank' ( id -- a ) CELLSZ * _bank + ;
: bank@ ( opmod -- n ) bankid@ bank' @ ;
: newbankedop ( n -- opmod ) newbankid tuck bank' ! 20 lshift ;

: r) $1c0 or 1 to+ _argcnt ;
: r) $1c0 or to1+ _argcnt ;

: _ doer ( reg -- ) , does> @ ( reg ) $c0 or 1 to+ _argcnt ;
: _ doer ( reg -- ) , does> @ ( reg ) $c0 or to1+ _argcnt ;
0 _ al    1 _ cl    2 _ dl    3 _ bl    4 _ ah    5 _ ch    6 _ dh    7 _ bh
8 _ es    9 _ cs    10 _ ss   11 _ ds   12 _ fs   13 _ gs
$10 _ cr0 $12 _ cr2 $13 _ cr3


@@ 77,7 77,7 @@ $100 _ ax $101 _ cx $102 _ dx $103 _ bx $104 _ sp $105 _ bp $106 _ si $107 _ di

: _d) ( opmod n -- opmod )
  dip $107 and | tuck dispmod 6 lshift or swap newbankedop or ;
: _ doer ( reg -- ) , does> real# @ swap _d) 1 to+ _argcnt ;
: _ doer ( reg -- ) , does> real# @ swap _d) to1+ _argcnt ;
0 _ bx+si) 1 _ bx+di) 2 _ bp+si) 3 _ bp+di) 4 _ si+) 5 _ di+) 6 _ _bp+) 7 _ bx+)
: bp+) ?dup if _bp+) else 1 _bp+) 0 over bankid@ bank' ! then ;


M fs/comp/c/egen.fs => fs/comp/c/egen.fs +1 -1
@@ 142,7 142,7 @@ code _callA branchA,
  swap CDecl type CDecl :find# tuck CDecl offset ( field-cdecl eop offset )
  over ExprOp :?>W i) +, ( field-cdecl eop ) tuck ExprOp :cdecl!
  dup ExprOp cdecl CDecl :reference? not if
    1 over to+ ExprOp lvl ExprOp :* then ;
    dup to1+ ExprOp lvl ExprOp :* then ;

\ parses, if possible, a postfix operator. If none, this is a noop.
\ We parse postfix args as long as there are any.

M fs/comp/c/expr.fs => fs/comp/c/expr.fs +2 -2
@@ 64,10 64,10 @@ struct[ ExprOp
    dup type DEREF = if target exit then
    dup cdecl CDecl :reference? if exit then
    dup :iscdecl? _assert
    0 REF :new ( tgt eop ) 2dup :copymeta tuck to target 1 over to+ lvl ;
    0 REF :new ( tgt eop ) 2dup :copymeta tuck to target dup to1+ lvl ;
  : :* ( self -- eop )
    0 DEREF :new 2dup :copymeta tuck to target
    dup lvl if -1 over to+ lvl else dup cdecl CDecl type over :cdecl! then ;
    dup lvl if dup to1- lvl else dup cdecl CDecl type over :cdecl! then ;
  : :cdecl ( cdecl -- eop ) 0 CDECL :new ( cdecl eop ) tuck :cdecl! ;
  : :basesz cdecl CDecl type typesize ;
  : :unsigned? cdecl typeunsigned? ;

M fs/comp/c/tok.fs => fs/comp/c/tok.fs +1 -1
@@ 16,7 16,7 @@ $400 Scratchpad :new structbind Scratchpad _pad
: _assert ( f -- ) not if _err then ;

: cctok$ 1 to curline 1 to _firstchar ;
: ?line+ ( c -- c ) dup LF = if 1 to+ curline 1 to _firstchar then ;
: ?line+ ( c -- c ) dup LF = if to1+ curline 1 to _firstchar then ;

\ Tokenization
64 const MAXTOKSZ

M fs/doc/dict.txt => fs/doc/dict.txt +4 -22
@@ 124,9 124,6 @@ r@         --              *I* Compile a push of current RS top to PS.
r>         --              *I* Equivalent to r@ rdrop
>r         --              *I* Compiles a RS grow of 4 bytes followed by a pop
                           of PS into that new RS space.
r+,        n --            Compile a RS grow (n is negative) or shrink (n is
                           positive) operation by n bytes.
p+,        n --            Same as r+, but for PS.
scnt       -- n            Number of elements in PS, excluding "n".
rcnt       -- n            Number of elementS in RS, excluding this call.
stack?     --              Error out if scnt < 0.


@@ 139,6 136,8 @@ width", a value that can be 1, 2 or 4 depending of the width of the operation.
@          a -- n        *B* Fetch n at address a.
!          n a --        *B* Store n at address a.
+!         n a --        *B* Add n to value stored at address a.
1+!        a --          *B* Same a "1 +!" but faster
1-!        a --          *B* Same a "-1 +!" but faster
@!         n1 a -- n2    *B* Fetch n2 at address a, then store n1 at address a.
@+         a -- a+bw n   *B* Fetch n at address a and increase a.
!+         n a -- a+bw   *B* Store n at address a and increase a.


@@ 374,30 373,13 @@ after a literal that yields the address of the word which obeys "to" semantics.

to    --> !
to+   --> +!
to1+   --> 1+!
to1-   --> 1-!
to'   --> noop
to@!  --> @!
to@+  --> @@+
to!+  --> @!+

## A register

All "A register" words are compiler words. Calling them doesn't execute their
description, it compiles native code that performs the description.

RSP>A,    --   Copies RS pointer to A.
PSP>A,    --   Copies PS pointer to A.
LIT>A,    n -- Copies "n" to A.
>A,       --   Pops PS into A.
A>,       --   *A* Pushes A to PS.
A+,       n -- Adds "n" to A.
[A]+,     n -- Adds "n" to 4b location A points to.
A@,       --   *AB* Equivalent to "A>, @"
A!,       --   *AB* Equivalent to "A> !"
A+!,      --   *AB* Equivalent to "A> +!"
A@!,      --   *AB* Equivalent to "A> @!"
[A]@,     --   *AB* Equivalent to "A> @ @"
[A]!,     --   *AB* Equivalent to "A> @ !"

## Templates

bi X | Y      --> dup X swap Y        a -- x y

M fs/fs/fat.fs => fs/fs/fat.fs +1 -1
@@ 151,7 151,7 @@ $e5 const DIRFREE
\ write multiple sectors from buf
: writesectors ( sec u buf self -- ) to self
  rot >r swap for ( buf ) \ V1=sec
    V1 over self :drv :sec! 1 to+ V1 self :drv secsz + next ( buf )
    V1 over self :drv :sec! to1+ V1 self :drv secsz + next ( buf )
  -1 self to bufsec drop rdrop ;

: writecluster ( cluster src self -- ) >r

M fs/fs/fatlo.fs => fs/fs/fatlo.fs +1 -1
@@ 153,7 153,7 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
\ read multiple sectors in buf
: :readsectors ( sec u buf self -- ) >r \ V1=self
  rot >r swap for ( buf ) \ V2=sec
    V2 over V1 :drv :sec@ 1 to+ V2 V1 secsz + next ( buf ) drop 2rdrop ;
    V2 over V1 :drv :sec@ to1+ V2 V1 secsz + next ( buf ) drop 2rdrop ;

: :readcluster ( cluster dst self -- ) >r
  over 2 - $fff6 > if abort" cluster out of range!" then

M fs/lib/fmt.fs => fs/lib/fmt.fs +1 -1
@@ 22,7 22,7 @@ struct+[ IO
  : :printf ( nX ... n0 fmt self -- ) >r >r \ V1=self V2=fmt
    8b to@+ V2 ( len ) for ( nX ... n0 )
      8b to@+ V2 dup '%' = if
        drop -1 to+ i 8b to@+ V2 case
        drop to1- i 8b to@+ V2 case
          'b' of = V1 :.x1 endof
          'w' of = V1 :.x2 endof
          'x' of = V1 :.x endof

M fs/lib/ll.fs => fs/lib/ll.fs +1 -1
@@ 11,6 11,6 @@
: llfind ( elem ll -- f )
  0 to llidx 0 to llprev begin ( elem line )
    2dup <> while
    1 to+ llidx dup to llprev
    to1+ llidx dup to llprev
    llnext dup while repeat then ( elem line )
  nip bool ;

M fs/lib/str.fs => fs/lib/str.fs +1 -1
@@ 17,7 17,7 @@ create _buf STR_MAXSZ allot
:iterator rfor ( a u -- )
  ?dup if
    to k to i 0 to j
    begin yield 1 to+ i 1 to+ j j k >= until
    begin yield to1+ i to1+ j j k >= until
    else drop then unyield ;

: [str]? ( str a u -- idx ) rot >r ( a u ) \ V1=str

M fs/sys/grid.fs => fs/sys/grid.fs +1 -1
@@ 32,7 32,7 @@ extends ByteWriter struct[ Grid

  \ called in "spit" mode
  : _spit ( c self -- ) >r \ V1=self V2=c
    r@ spitpos r@ :cell! 1 to+ r> spitpos ;
    r@ spitpos r@ :cell! r> to1+ spitpos ;

  : :spiton ( pos self -- )
    tuck to spitpos ['] _spit swap ['] :writebyte sfield! ;

M fs/sys/rdln.fs => fs/sys/rdln.fs +1 -1
@@ 13,7 13,7 @@ here const in)
extends MemIO struct[ Rdln
  : :lntype ( c self -- f ) >r \ V1=self
    dup bs? if ( c )
      drop V1 ptr V1 buf( > if -1 V1 to+ ptr BS emit then spc> BS emit 0
      drop V1 ptr V1 buf( > if V1 to1- ptr BS emit then spc> BS emit 0
    else ( c ) \ non-BS
      cr>lf V1 )buf V1 ptr - 1 = if drop LF then
      dup emitv dup V1 :putc SPC <

M fs/text/pager.fs => fs/text/pager.fs +1 -1
@@ 13,7 13,7 @@ create _nextpage ," Next Page...\n"
    _nextpage 13 V2 V1 execute 13 <> if abort" pager error" then
    key ESC = if quit then then
  2dup LF rot> [c]? dup 0>= if ( a n idx )
    1 to+ _cnt nip 1+ ( a n )
    to1+ _cnt nip 1+ ( a n )
  else ( a n -1 ) drop then r> ;

: spager$

M fs/xcomp/bootlo.fs => fs/xcomp/bootlo.fs +12 -2
@@ 32,6 32,12 @@ code w! branch, drop
code +! W>A, drop, A) +, A) !, drop, exit,
code16b W>A, drop, A) 16b) +, A) 16b) !, drop, exit,
code8b W>A, drop, A) 8b) +, A) 8b) !, drop, exit,
code 1+! 1 W) [+n], drop, exit,
code16b 1 W) 16b) [+n], drop, exit,
code8b 1 W) 8b) [+n], drop, exit,
code 1-! -1 W) [+n], drop, exit,
code16b -1 W) 16b) [+n], drop, exit,
code8b -1 W) 8b) [+n], drop, exit,
code @! W>A, drop, A) @!, exit,
code16b W>A, drop, A) 16b) @!, exit,
code8b W>A, drop, A) 8b) @!, exit,


@@ 160,6 166,10 @@ code (does) r> W>A, W) @, W<>A, CELLSZ W+n, branchA,
_to to ! _!,
: _+!, dup +, _!, ; :16b dup 16b) +, 16b _!, ; :8b dup 8b) +, 8b _!, ;
_to to+ +! _+!,
: _1+!, 1 swap [+n], ; :16b 1 swap 16b) [+n], ; :8b 1 swap 8b) [+n], ;
_to to1+ 1+! _1+!,
: _1-!, -1 swap [+n], ; :16b -1 swap 16b) [+n], ; :8b -1 swap 8b) [+n], ;
_to to1- 1-! _1-!,
_to to@! @! @!,
: _@@+, dup, dup [@], 4 swap [+n], ;
:16b dup, dup 16b) [@], 2 swap [+n], ;


@@ 224,10 234,10 @@ alias execute | immediate
: break 16 rs+, [compile] ahead to _breaklbl ; immediate

:iterator for ( n -- )
  ?dup if to i begin yield -1 to+ i i not until then unyield ;
  ?dup if to i begin yield to1- i i not until then unyield ;

:iterator for2 ( lo hi -- )
  2dup < if to j to i begin yield 1 to+ i i j >= until else 2drop then unyield ;
  2dup < if to j to i begin yield to1+ i i j >= until else 2drop then unyield ;

: fill ( a u c -- ) rot> over + for2 dup i c! next drop ;
: allot0 ( n -- ) here over 0 fill allot ;