duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 5a7c26b53082b3f3127bc24fcd008427c298aded
parent 8436cbc10ee990e1f64f44929f68348d5142efe3
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Fri, 17 Jun 2022 09:40:44 -0400

cc: parse the "unsigned" keyword and apply it to types

Diffstat:
Mfs/cc/ast.fs | 63+++++++++++++++++++++++++++++----------------------------------
Mfs/cc/cc.fs | 2+-
Mfs/cc/tok.fs | 11++++++++++-
Mfs/cc/type.fs | 21++++++++++-----------
Mfs/tests/cc/test.c | 4++--
5 files changed, 52 insertions(+), 49 deletions(-)

diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs @@ -98,18 +98,13 @@ ASTIDCNT wordtbl astdatatbl ( node -- node ) : newnode ( parent astid -- newnode ) createnode ( parent node ) dup rot addnode ( node ) ; -\ if not 0, next _nextt call will fetch token from here -0 value nexttputback : _err ( -- ) abort" parsing error" ; : _assert ( f -- ) not if _err then ; -: _nextt - nexttputback ?dup if 0 to nexttputback exit then - nextt ?dup not if abort" expecting token!" then ; \ Takes a token and returns the corresponding typedef (not AST type). \ For now, we always return 1 on "int". : isType? ( tok -- f ) S" int" s= ; -: expectType ( tok -- type ) findtype not if _err then ( type ) ; +: expectType ( tok -- type ) parseType not if _err then ( type ) ; : expectConst ( tok -- n ) dup parse if nip else _err then ; : isIdent? ( tok -- f ) dup 1+ c@ identifier1st? not if drop 0 exit then @@ -117,7 +112,7 @@ ASTIDCNT wordtbl astdatatbl ( node -- node ) : expectIdent ( tok -- tok ) dup isIdent? _assert ; : expectChar ( tok c -- ) over 1+ c@ = _assert dup c@ 1 = _assert drop ; -: read; ( -- ) _nextt ';' expectChar ; +: read; ( -- ) nextt ';' expectChar ; \ Parse words @@ -136,17 +131,17 @@ alias noop parseExpression ( tok -- node ) \ forward declaration \ 5. An expression inside () parens. : parseFactor ( tok -- node-or-0 ) dup S" (" s= if ( tok ) - drop _nextt parseExpression _nextt ')' expectChar exit then + drop nextt parseExpression nextt ')' expectChar exit then dup uopid if ( tok opid ) nip AST_UNARYOP createnode swap , ( opnode ) - _nextt parseFactor ?dup _assert over addnode ( opnode ) + nextt parseFactor ?dup _assert over addnode ( opnode ) exit then ( tok ) dup isIdent? if \ lvalue or FunCall - _nextt ( prevtok newtok ) dup S" (" s= if \ FunCall + nextt ( prevtok newtok ) dup S" (" s= if \ FunCall drop AST_FUNCALL createnode swap , begin ( node ) - _nextt dup parseFactor ?dup if \ an argument + nextt dup parseFactor ?dup if \ an argument nip over addnode - _nextt dup S" ," s= if drop else to nexttputback then 0 + nextt dup S" ," s= if drop else to nexttputback then 0 else \ not an argument ')' expectChar 1 then until ( node ) else ( prevtok newtok ) \ lvalue @@ -162,13 +157,13 @@ alias noop parseExpression ( tok -- node ) \ forward declaration \ 3. A binaryop containing two expressions. : _ ( tok -- exprnode ) \ parseExpression \ tok is expected to be a factor - parseFactor ?dup _assert _nextt ( factor nexttok ) + parseFactor ?dup _assert nextt ( factor nexttok ) dup bopid if ( factor tok binop ) nip ( factor binop ) AST_BINARYOP createnode swap , ( factor node ) - tuck addnode _nextt ( binnode tok ) + tuck addnode nextt ( binnode tok ) \ now, let's consume tokens as long as we have binops coming. begin ( bn tok ) - parseFactor ?dup _assert _nextt ( bn factor tok ) dup bopid if ( bn fn tok bopid ) + parseFactor ?dup _assert nextt ( bn factor tok ) dup bopid if ( bn fn tok bopid ) nip AST_BINARYOP createnode swap , ( bn1 fn bn2 ) \ another binop! who will get fn? bn1 or bn2? the one that has the \ best precedence! @@ -178,7 +173,7 @@ alias noop parseExpression ( tok -- node ) \ forward declaration else \ bn1 wins. add fn to bn1, bn1 to bn2, bn2 becomes bn rot over addnode ( bn2 bn1 ) over addnode ( bn2->bn ) then ( bn ) - _nextt 0 ( bn tok 0 ) + nextt 0 ( bn tok 0 ) else ( bn fn tok ) \ not a binop \ tok becomes nexttok and we add fn to bn to complete the chain rot> over addnode swap 1 ( bn tok 1 ) then @@ -191,24 +186,24 @@ current to parseExpression : parseDeclare ( type parentnode -- dnode ) 0 begin ( type pnode *lvl ) - _nextt dup S" *" s= if drop 1+ 0 else 1 then until ( type pnode *lvl tok ) + nextt dup S" *" s= if drop 1+ 0 else 1 then until ( type pnode *lvl tok ) expectIdent rot ( type *lvl name pnode ) AST_DECLARE newnode ( type *lvl name dnode ) swap , ( type *lvl dnode ) rot> , , ( dnode ) ; : parseDeclarationList ( type stmtsnode -- ) - parseDeclare _nextt '=' expectChar dup data1 ( dnode name ) + parseDeclare nextt '=' expectChar dup data1 ( dnode name ) swap parentnode AST_BINARYOP newnode ( name anode ) 12 ( = ) , AST_LVALUE newnode ( name lvnode ) swap , parentnode ( anode ) - _nextt parseExpression read; ( anode expr ) swap addnode ; + nextt parseExpression read; ( anode expr ) swap addnode ; : parseArgSpecs ( funcnode -- ) - _nextt '(' expectChar AST_ARGSPECS newnode _nextt ( argsnode tok ) + nextt '(' expectChar AST_ARGSPECS newnode nextt ( argsnode tok ) dup S" )" s= if 2drop exit then begin ( argsnode tok ) expectType over parseDeclare drop - _nextt dup S" )" s= if 2drop exit then - ',' expectChar _nextt again ; + nextt dup S" )" s= if 2drop exit then + ',' expectChar nextt again ; alias noop parseStatements ( funcnode -- ) \ forward declaration @@ -216,27 +211,27 @@ alias noop parseStatements ( funcnode -- ) \ forward declaration 2 wordtbl statementhandler ( snode -- snode ) :w ( return ) dup AST_RETURN newnode ( snode rnode ) - _nextt parseExpression read; ( snode rnode expr ) + nextt parseExpression read; ( snode rnode expr ) swap addnode ( snode ) ; :w ( if ) dup AST_IF newnode ( snode ifnode ) - _nextt '(' expectChar - _nextt parseExpression ( sn ifn expr ) over addnode - _nextt ')' expectChar + nextt '(' expectChar + nextt parseExpression ( sn ifn expr ) over addnode + nextt ')' expectChar dup parseStatements ( snode ifnode ) - _nextt dup S" else" s= if ( sn ifn tok ) + nextt dup S" else" s= if ( sn ifn tok ) drop parseStatements else to nexttputback drop then ; : _ ( parentnode -- ) \ parseStatements - _nextt '{' expectChar AST_STATEMENTS newnode _nextt + nextt '{' expectChar AST_STATEMENTS newnode nextt begin ( snode tok ) dup S" }" s= if 2drop exit then dup statementnames sfind dup 0< if ( snode tok -1 ) - drop dup findtype if ( snode tok type ) + drop dup parseType if ( snode tok type ) nip over parseDeclarationList else ( snode tok ) parseExpression over addnode read; then ( snode ) else ( snode tok idx ) nip statementhandler swap wexec then ( snode ) - _nextt again ; + nextt again ; current to parseStatements : parseFunction ( unitnode tok -- ) @@ -245,7 +240,7 @@ current to parseStatements : parseast ( -- ) AST_UNIT createnode dup to curunit - nextt ?dup not if exit then begin ( unitnode tok ) - findtype _assert drop - _nextt expectIdent over swap parseFunction ( unitnode ) - nextt ?dup not until ( unitnode ) drop ; + nextt? ?dup not if exit then begin ( unitnode tok ) + parseType _assert drop + nextt expectIdent over swap parseFunction ( unitnode ) + nextt? ?dup not until ( unitnode ) drop ; diff --git a/fs/cc/cc.fs b/fs/cc/cc.fs @@ -4,9 +4,9 @@ f<< lib/str.fs f<< lib/wordtbl.fs f<< lib/xdict.fs f<< asm.fs -f<< cc/type.fs f<< cc/vm.fs f<< cc/tok.fs +f<< cc/type.fs f<< cc/tree.fs f<< cc/ast.fs f<< cc/map.fs diff --git a/fs/cc/tok.fs b/fs/cc/tok.fs @@ -61,7 +61,7 @@ create _ 8 c, ," 09AZaz__" over >r c!+ ( c a ) begin c!+ next drop r> ( str ) ; \ Returns the next token as a string or 0 when there's no more token to consume. -: nextt ( -- tok-or-0 ) +: nextt? ( -- tok-or-0 ) tonws dup not if ( EOF ) exit then ( c ) dup isSym1? if ( c ) cc< 2dup isSym2? if ( c1 c2 ) @@ -79,3 +79,12 @@ create _ 8 c, ," 09AZaz__" Ac!+ cc< dup identifier? not until to putback r> ( buf ) A> over 1+ - ( tok len ) over c! r>A then ; + +\ if not 0, next nextt call will fetch token from here +0 value nexttputback + +\ Fetch the next token, aborting if there's none. Also, apply the "putback" +\ logic. +: nextt ( -- tok ) + nexttputback ?dup if 0 to nexttputback exit then + nextt? ?dup not if abort" expecting token!" then ; diff --git a/fs/cc/type.fs b/fs/cc/type.fs @@ -1,23 +1,22 @@ \ C compiler types +\ Requires lib/str cc/tok \ All information related to a basic type fits in a 32b integer, so that's \ how "type" is passed around. Structure: \ b2:0 = size. 0=0 1=8 2=16 3=32 4+=reserved for future use \ b3 = sign. 0=unsigned 1=signed -4 const TYPECNT -create types - $00 , \ void - $05 , \ char - $06 , \ short - $07 , \ int - -TYPECNT stringlist typenames "void" "char" "short" "int" +4 stringlist typenames "void" "char" "short" "int" create _ 0 c, 8 c, 16 c, 32 c, : typesize ( type -- size-in-bytes ) 3 and _ + c@ ; : typesigned? ( type -- flags ) 2 rshift 1 and ; -: findtype ( name -- type? f ) - typenames sfind dup 0>= if 4 * types + @ 1 else drop 0 then ; +\ Unlike ANSI C, "signed" doesn't exist and "unsigned" needs to be before the +\ type name. +: parseType ( tok -- type? f ) + dup S" unsigned" s= if drop $04 nextt else $00 swap then ( type tok ) + typenames sfind dup 0>= if ( type idx ) or 1 else 2drop 0 then ( type ) ; -: printtype ( type -- ) 3 and typenames slistiter stype ; +: printtype ( type -- ) + dup typesigned? if ." unsigned " then + 3 and typenames slistiter stype ; diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c @@ -12,8 +12,8 @@ int boolops() { return 66 < 54 && 2 == 2; } int variables() { - int foo = 40; - int _bar = 2; + unsigned int foo = 40; + unsigned int _bar = 2; _bar = foo + _bar; return foo + _bar; }