~vdupras/duskos

727e15306d0f16c8a81a223726dfa0960d8f07ff — Virgil Dupras 16 days ago 57ffa38
bootlo: add :realias

See doc/usage
M fs/comp/c/egen.fs => fs/comp/c/egen.fs +2 -5
@@ 191,7 191,7 @@ MAXLITSZ Stack :new structbind Stack _list
\ 8. a typecast followed by a factor
\ 9. NULL
\ 10. sizeof()
: _ ( tok -- eop ) case ( )
:realias parseFactor ( tok -- eop ) case ( )
    '(' of isChar?^
      \ can be an expression or a typecast
      nextt dup parseType if ( tok type )


@@ 218,7 218,6 @@ MAXLITSZ Stack :new structbind Stack _list
      r@ findIdent ?dup _assert ExprOp :cdecl parsePostfixOp endof
    r@ parse if ExprOp :const else _err then
  endcase ;
current ' parseFactor realias

: bothconst? ( left right -- f ) ExprOp :isconst? swap ExprOp :isconst? and ;



@@ 253,10 252,8 @@ current ' parseFactor realias
\ An expression can be 2 things:
\ 1. a factor
\ 2. A binaryop containing two expressions.
: _ ( tok -- eop ) \ parseExpression
:realias parseExpression ( tok -- eop )
  \ first tok is always a factor
  parseFactor nextt ( left tok )
  dup bopid if ( left tok binop )
    nip parseRExpr else to nexttputback then ;

current ' parseExpression realias

M fs/comp/c/fgen.fs => fs/comp/c/fgen.fs +1 -2
@@ 125,12 125,11 @@ MAXSWITCHCASES << Stack :new structbind Stack _cases
'w _do             'w _switch

0 value _laststmtid
: _ ( tok -- ) \ parseStatement
:realias parseStatement ( tok -- )
  dup statementnames sfind dup >r dup 0< if ( tok -1 ) \ V1=stmtidx
    drop parseExpression ExprOp :release expr$ read;
    else nip statementhandler swap wexec then
  r> to _laststmtid ;
current ' parseStatement realias

\ When there's variable initialization code, it has to come before the prelude
\ and we jump to it after we've created the stack frame.

M fs/comp/c/ptype.fs => fs/comp/c/ptype.fs +2 -4
@@ 43,7 43,7 @@ alias _err parseDeclarator ( type -- cdecl ) \ forward declaration
    r> to nexttputback exit
  endcase again ;

: _parseDeclarator ( type -- cdecl )
:realias parseDeclarator ( type -- cdecl )
  0 over cdecl? if over CDecl :funcptr? if
    dip bi CDecl type | CDecl lvl | + then then ( type lvl )
  begin ( type lvl )


@@ 62,7 62,6 @@ alias _err parseDeclarator ( type -- cdecl ) \ forward declaration
  else ( type lvl tok )
    dup isIdent? not if to nexttputback NULLSTR then ( type lvl name )
    rot CDecl :new ( lvl cdecl ) tuck to CDecl lvl then _post ;
current ' parseDeclarator realias

: _parseStruct ( -- cdecl )
  nextt dup isIdent? if nextt else NULLSTR swap then


@@ 83,7 82,7 @@ current ' parseDeclarator realias
\ part without the "*" part or the name part. The result can be a "base" type
\ (type < $100) or a CDecl if the type is a struct, union or enum.
create _ubuf $10 allot
: _parseType ( tok -- type? f ) \ ." parseType " dup stype nl>
:realias parseType ( tok -- type? f )
  dup S" typedef" s= if
    drop nextt parseType _assert parseDeclarator ( cdecl )
    dup addTypedef 1 exit then


@@ 91,4 90,3 @@ create _ubuf $10 allot
    dup S" unsigned" s= if drop 8 nextt else 0 swap then ( type tok )
    dup typenames sfind dup 0>= if ( type tok idx ) nip or 1
      else drop nip findTypedef ( type-or-0 ) ?dup bool then then ;
current ' parseType realias

M fs/comp/c/type.fs => fs/comp/c/type.fs +10 -12
@@ 21,8 21,8 @@ Arena :new const _tarena \ Temporary
: _assert ( f -- ) not if _err then ;

\ Forward declaration implemented below
alias _err _typesize  ( type -- size-in-bytes )
alias _err _printtype ( type -- )
alias _err typesize  ( type -- size-in-bytes )
alias _err printtype ( type -- )

$0 const TYPE_VOID
$1 const TYPE_CHAR


@@ 102,12 102,12 @@ struct[ CDecl
  : :size ( self -- size )
    dup :isarg? over :funcsig? or if drop CELLSZ exit then
    0 swap begin ( res cdecl ) ?dup while
      tuck dup lvl if 4 else dup type _typesize then ( cdecl res cdecl n )
      tuck dup lvl if 4 else dup type typesize then ( cdecl res cdecl n )
      swap nbelem 1 max * + swap llnext repeat ( res ) ;

  \ When the CDecl is an array, return the size of a single element.
  : :elemsize ( self -- size )
    dup nbelem _assert dup lvl if drop 4 else type _typesize then ;
    dup nbelem _assert dup lvl if drop 4 else type typesize then ;

  : :argssize ( self -- size ) dup :funcsig? _assert args llcnt CELLSZ * ;
  : :offset! ( off self -- off+size ) 2dup to offset :size + ;


@@ 117,13 117,13 @@ struct[ CDecl
  : :find ( name self -- cdecl ) llnext dup if _ then nip ;
  : :find# :find dup _assert ;

  : _.children begin ?dup while dup _printtype ." , " llnext repeat ;
  : _.children begin ?dup while dup printtype ." , " llnext repeat ;
  create _storagechars ," RPMN"
  : :. ( self -- ) >r \ print without children
    r@ storage _storagechars + c@ emit spc>
    r@ offset if '+' emit r@ offset .x? spc> then
    r@ :struct? if ." struct" else
      '{' emit r@ type _printtype '}' emit
      '{' emit r@ type printtype '}' emit
      r@ lvl for '*' emit next then
    r@ name c@ if spc> r@ name stype then
    r@ nbelem if '[' emit r@ nbelem . ']' emit then


@@ 137,9 137,9 @@ struct[ CDecl
    dup name NEXTWORD ! struct[ llnext begin ( cdecl )
      ?dup while
      dup name NEXTWORD ! dup nbelem if ( cdecl )
        dup type _typesize over nbelem * sfield'
        dup type typesize over nbelem * sfield'
      else ( cdecl )
        dup type _typesize case
        dup type typesize case
          1 of = sfieldb endof
          2 of = sfieldw endof
          sfield endcase then ( cdecl )


@@ 170,13 170,11 @@ create _ssymbols 0 , 0 c, \ static
  dup cdecl? if CDecl type ensurebasetype then ;
: typeunsigned? ( type -- f ) ensurebasetype 8 and bool ;

: printtype ( type -- )
:realias printtype ( type -- )
  dup cdecl? if CDecl :. else
    dup typeunsigned? if ." unsigned " then
    7 and typenames slistiter stype then ;
current ' _printtype realias

create _ 8 nc, 0 1 2 4 0 0 0 0
: typesize ( type -- size-in-bytes )
:realias typesize ( type -- size-in-bytes )
  dup cdecl? if CDecl :size else 7 and _ + c@ then ;
current ' _typesize realias

M fs/doc/dict.txt => fs/doc/dict.txt +2 -0
@@ 333,6 333,8 @@ which can then be executed to have the desired effect.
:          "x" --   Create entry x and begin compiling.
:8b        --       Create a 8b variant to the latest word.
:16b       --       Create a 16b variant to the latest word.
:realias   --       Compile a word while at the same time "realias"ing the word
                    it shadows to this new word.
;          --       *I* Compile a return from call and then stop compiling.
litn       n --     Compile a literal with value n.
execute,   a --     Compile a call to address a.

M fs/doc/usage.txt => fs/doc/usage.txt +19 -0
@@ 228,6 228,25 @@ elsewhere. If you do, make sure that the word is big enough for a native jump.
For example, using realias on the word "noop", which only contains a "return"
op, would likely corrupt the dictionary entry of the following word.

Aliases have two main usages: dynamically pluggable words, or forward
declarations. For the latter type, there is also the syntactically more pleasant
word ":realias", which is a combination of, drum roll, ":" and "realias" and can
be used thus:

    alias abort foo \ Forward declaration
    : bar foo ;
    :realias foo bar ;

It is the equivalent of:

    alias abort foo \ Forward declaration
    : bar foo ;
    : _ bar ;
    current ' foo realias

except that further references to "foo" will link directly to the actual word
rather than going through the alias.

## Linked lists

Linked lists are a fundamental data structure in Dusk. They are simply addresses

M fs/fs/fat.fs => fs/fs/fat.fs +5 -10
@@ 113,13 113,12 @@ $e5 const DIRFREE
  r> findfreedirentry dup DirEntry SZ 0 fill ( direntry )
  fnbuf( over DirEntry NAMESZ move ( direntry ) ;

: _newfile ( dirid name self -- id ) >r
:realias :newfile ( dirid name self -- id ) >r
  r@ _newentry ( dirent ) r@ writecursector r> :getid ;
current ' :newfile realias

: _makedir ( dirent -- dirent ) $10 over to DirEntry attr ;

: _newdir ( dirid name self -- id )
:realias :newdir ( dirid name self -- id )
  r! allocatecluster0 >r ( dirid name ) \ V1=self V2=cluster
  V1 _newentry ( dirent ) _makedir ( dirent )
  V2 over to DirEntry cluster V1 writecursector ( dirent )


@@ 131,7 130,6 @@ current ' :newfile realias
  dup DirEntry NAMESZ SPC fill '.' over c!+ '.' swap c! ( id buf )
  _makedir ( id buf ) V3 swap to DirEntry cluster
  2rdrop r> writecursector ( id ) ;
current ' :newdir realias

\ write multiple sectors from buf
: writesectors ( sec u buf self -- ) >r \ V1=self


@@ 144,13 142,11 @@ current ' :newdir realias
  swap r@ :FirstSectorOfCluster ( dst sec )
  swap r@ secpercluster swap r> writesectors ;

: _info ( id self -- info ) FATInfo :read ;
current ' :info realias
:realias :info ( id self -- info ) FATInfo :read ;

\ TODO: deallocate the chain before clearing the entry
: _remove ( id self -- )
:realias :remove ( id self -- )
  tuck :getdirentry ( dirent ) DIRFREE swap c! writecursector ;
current ' :remove realias

\ Read next sector if a sequential read is available, else return false.
: :nextsector? ( self -- f )


@@ 163,11 159,10 @@ current ' :remove realias
  dup DirEntry :lastentry? if drop 0 else
    dup DirEntry :iterable? not if V1 _next then then ( entry ) rdrop ;

: _iter ( dirid previd self -- id-or-0 ) >r >r ( dirid ) \ V1=self V2=previd
:realias :iter ( dirid previd self -- id-or-0 ) >r >r \ V1=self V2=previd
  V1 :getdirentry V1 :readdir V1 :dirwin :buf( DirEntry SZ - V2 if begin ( entry )
      V1 _next dup while dup V1 :getid V2 <> while repeat then then ( entry-or-0 )
  dup if V1 _next dup if V1 :getid then then 2rdrop ;
current ' :iter realias

: :patchlo ( fs -- ) 1 swap to flags ;
: :mountvolume ( drv -- fs ) FAT :mountvolume dup :patchlo ;

M fs/sys/loop.fs => fs/sys/loop.fs +1 -2
@@ 9,11 9,10 @@

: _word@ ( ll -- ) CELLSZ + @ ;

: _idle ( -- )
:realias idle ( -- )
  _current ?dup not if _loop then
  ?dup if
    dup _word@ execute llnext to _current then ;
current ' idle realias

: loopadd ( w -- ) _loop ?dup not if to' _loop then lladd drop , ;


M fs/xcomp/bootlo.fs => fs/xcomp/bootlo.fs +2 -2
@@ 196,6 196,7 @@ alias @ llnext
: metaadd ( id entry -- ) 'emeta lladd drop , ;

: realias ( 'new 'tgt -- ) to@! here swap branch, drop to here ;
: :realias ' sysdict curword entry here swap realias ] ;
: _ ( w -- w-or-0 ) dup ['] noop = if drop 0 then ;
: chain ( w1 w2 -- w )
  _ swap _ tuck over and? if


@@ 250,8 251,7 @@ code [c]? ( c a u -- i )
$20 const SPC $0d const CR $0a const LF $08 const BS $1b const ESC
alias drop emit
: nl> LF emit ; : spc> SPC emit ;
: _ ( a u ) for c@+ emit next drop ;
current ' rtype realias
:realias rtype ( a u ) for c@+ emit next drop ;
: stype ( str -- ) c@+ rtype ;
create _escapes 'n' c, 'r' c, '0' c,
create _repl    LF  c, CR  c, 0   c,