duskos

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

commit ab47412710686cf4608a96559bfcdc7a1c9d75df
parent c387d55843c5ddacde83b66f718fb1161be31af9
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue, 21 Mar 2023 13:18:57 -0400

halcc: begin type reform

Since I'm rewriting the thing, I might as well fix CType at the same time.
My first design doesn't model the space well and ends up being unnecessarily
complex. Let's try something new.

Diffstat:
Mfs/comp/c/cc.fs | 8++------
Mfs/comp/c/egen.fs | 12++++++------
Mfs/comp/c/expr.fs | 12++++++------
Mfs/comp/c/fgen.fs | 52++++++++++++++++++++++++++--------------------------
Mfs/comp/c/func.fs | 10+++++-----
Mfs/comp/c/gen.fs | 16++++++++--------
Mfs/comp/c/ptype.fs | 66++++++++++++++++++++++++++----------------------------------------
Mfs/comp/c/type.fs | 120++++++++++++++++++++++++++-----------------------------------------------------
Mfs/tests/comp/c/cc.fs | 2+-
Mfs/tests/comp/c/test2.c | 16++++++++++++++++
10 files changed, 135 insertions(+), 179 deletions(-)

diff --git a/fs/comp/c/cc.fs b/fs/comp/c/cc.fs @@ -13,11 +13,7 @@ : :c cctok$ nextt cparse ; : calias - cctok$ ' nextt parseType _assert parseDeclarator ( w ctype ) - read; dup addSymbol to CType offset ; + cctok$ ' nextt parseType _assert parseDeclarator ( w cdecl ) + read; dup addSymbol to CDecl offset ; : cc<< ( -- ) ['] cc1, word with-stdin-file ; - -:c typedef unsigned char uchar ; -:c typedef unsigned short ushort ; -:c typedef unsigned int uint ; diff --git a/fs/comp/c/egen.fs b/fs/comp/c/egen.fs @@ -47,16 +47,16 @@ UOPSCNT wordtbl _tbl ( res -- res ) \ need to restore psoff to its initial level *without actually adjusting* \ because it's the callee's responsibility to free its arguments. : _funcall ( res -- res ) psoff dup >r >r \ V1=psinitlvl V2=pslvl - dup Result :isctype? _assert ')' readChar? not if begin ( funcres tok ) + dup Result :iscdecl? _assert ')' readChar? not if begin ( funcres tok ) parseExpression Result :?>W psoff V2 - ?dup if dup ps+, neg to+ psoff then CELLSZ to+ V2 ',' readChar? while nextt repeat ')' expectChar then ( funcres ) - dup Result :ctype# dup CType :funcsig? if - nip dup CType offset execute, - else abort" TODO: dynamic calls" then ( ctype ) + dup Result :cdecl# dup CDecl :funcsig? if + nip dup CDecl offset execute, + else abort" TODO: dynamic calls" then ( cdecl ) rdrop r> ( psinitlvl ) to psoff Result currentW ?dup if PS- Result :release then - CType type if PS+ Result :W else Result :none then ; + CDecl type typesize if PS+ Result :W else Result :none then ; : _incdec, ( res incsz -- res ) swap bi+ Result :hal# | Result :?>W ( incsz res halop ) rot swap [+n], ; @@ -110,7 +110,7 @@ UOPSCNT wordtbl _tbl ( res -- res ) of uopid ( opid ) nextt parseFactor ( opid res ) _tbl rot wexec endof of isIdent? \ lvalue, FunCall or macro - r@ findIdent ?dup _assert Result :ctype parsePostfixOp endof + r@ findIdent ?dup _assert Result :cdecl parsePostfixOp endof r@ parse if Result :const else _err then endcase ; current ' parseFactor realias diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs @@ -10,7 +10,7 @@ struct[ Result 0 const NONE \ Nothing (probably a released W) 1 const CONST \ Is a constant (value in arg) 2 const W \ Value in W register - 3 const CTYPE \ CType pointer is in arg. + 3 const CDECL \ CDecl pointer is in arg. 4 const PS \ Result pushed to PS, offset in arg sfield type sfield arg @@ -25,13 +25,13 @@ struct[ Result : :none ( -- res ) 0 NONE :new ; : :const ( n -- res ) CONST :new ; : :W ( -- res ) :Wfree# 0 W :new dup to currentW ; - : :ctype ( ctype -- res ) CTYPE :new ; + : :cdecl ( cdecl -- res ) CDECL :new ; : :isW? ( self -- f ) type W = ; : :release ( self -- ) dup :isW? if 0 to currentW then NONE swap to type ; : :hal# ( self -- halop ) dup type case ( self ) CONST of = arg i) endof - CTYPE of = arg CType :halop endof + CDECL of = arg CDecl :halop endof PS of = arg PSP+) endof abort" :hal# error" endcase ; : :>W ( self -- ) @@ -44,8 +44,8 @@ struct[ Result : :iszero? bi arg 0 = | :isconst? and ; : :isone? bi arg 1 = | :isconst? and ; : :const# dup :isconst? _assert arg ; - : :isctype? ( self -- f ) type CTYPE = ; - : :ctype# dup :isctype? _assert arg ; + : :iscdecl? ( self -- f ) type CDECL = ; + : :cdecl# dup :iscdecl? _assert arg ; : :>PS dup :>W$ dup, PS+ PS over to type psoff neg swap to arg ; : :?freeCurrentW ( -- ) currentW ?dup if :>PS then ; : :?>W dup :isW? if drop else :?freeCurrentW :>W then ; @@ -56,7 +56,7 @@ struct[ Result : :* ( self -- ) 1 swap to+ lvl ; : :& ( self -- ) dup lvl if -1 swap to+ lvl else - :?freeCurrentW dup :ctype# CType :halop lea, W swap to type then ; + :?freeCurrentW dup :cdecl# CDecl :halop lea, W swap to type then ; ]struct BOPSCNT wordtbl _tbl ( a b -- n ) diff --git a/fs/comp/c/fgen.fs b/fs/comp/c/fgen.fs @@ -8,8 +8,8 @@ : _assert ( f -- ) not if _err then ; : _postlude - _curfunc CType :argssize ?dup if ps+, then - _locvars CType :size ?dup if rs+, then ; + _curfunc CDecl :argssize ?dup if ps+, then + _locvars CDecl :size ?dup if rs+, then ; alias noop parseStatement ( tok -- ) \ forward declaration @@ -52,49 +52,49 @@ current ' parseStatement realias 0 value _initcode : parseDeclLine ( type -- ) - parseDeclarator ( ctype ) - dup _locvars ?dup if CType :append else to _locvars then begin ( ctype ) - '=' readChar? if ( ctype ) + parseDeclarator ( cdecl ) + dup _locvars ?dup if CDecl :append else to _locvars then begin ( cdecl ) + '=' readChar? if ( cdecl ) _initcode not if here to _initcode then - nextt parseExpression ( ctype res ) - Result :>W$ dup CType :halop !, psneutral nextt then ( ctype tok ) - dup ';' isChar? not while ( ctype tok ) - ',' expectChar CType type parseDeclarator ( ctype ) - dup _locvars CType :append repeat ( ctype tok ) 2drop ; + nextt parseExpression ( cdecl res ) + Result :>W$ dup CDecl :halop !, psneutral nextt then ( cdecl tok ) + dup ';' isChar? not while ( cdecl tok ) + ',' expectChar CDecl type parseDeclarator ( cdecl ) + dup _locvars CDecl :append repeat ( cdecl tok ) 2drop ; -\ Given a ctype for a function body that has a proper offset field, but that +\ Given a cdecl for a function body that has a proper offset field, but that \ hasn't been added to the symbol list yet, check if we have a prototype in the \ symbols that correspond to this function. If yes, update the jump of that \ prototype. -: ?updateFunctionPrototype ( ctype -- ) - dup CType name findSymbol ?dup if - dup CType :funcsig? over CType :incomplete? and if ( ctype found ) - CType offset to@! here >r ( ctype ) - dup CType offset branch, drop r> to here ( ctype ) - else drop then then ( ctype ) drop ; +: ?updateFunctionPrototype ( cdecl -- ) + dup CDecl name findSymbol ?dup if + dup CDecl :funcsig? over CDecl :incomplete? and if ( cdecl found ) + CDecl offset to@! here >r ( cdecl ) + dup CDecl offset branch, drop r> to here ( cdecl ) + else drop then then ( cdecl ) drop ; \ '{' is already parsed -: parseFunctionBody ( ctype -- ) +: parseFunctionBody ( cdecl -- ) 0 to _locvars 0 to _initcode to _curfunc _litarena :reserve ( ) STORAGE_SF to@! curstorage >r begin nextt dup parseType while ( tok type ) nip parseDeclLine repeat ( tok ) to nexttputback r> to curstorage _initcode if [compile] ahead >r then - _curfunc CType :static? not if sysdict _curfunc CType name entry then ( ) - here _curfunc to CType offset ( ) + _curfunc CDecl :static? not if sysdict _curfunc CDecl name entry then ( ) + here _curfunc to CDecl offset ( ) _curfunc ?updateFunctionPrototype _curfunc addSymbol \ prelude: space for stack frame. "dup," is wiggle room for W - dup, _locvars CType :size ?dup if neg rs+, then + dup, _locvars CDecl :size ?dup if neg rs+, then _initcode ?dup if [compile] again r> [compile] then then 0 to _laststmtid parseStatements _laststmtid 1 <> if emitNullRet then \ emit implicit return if needed 0 to _curfunc ; -: parseFunctionProto ( ctype tok -- ) +: parseFunctionProto ( cdecl tok -- ) ';' expectChar dup addSymbol curstatic if - dup CType :incomplete! here ['] _err branch, drop + dup CDecl :incomplete! here ['] _err branch, drop \ allot a little extra space in case the replacement jump is wider CELLSZ allot - else dup CType name sysdict @ find ?dup not if - CType name stype abort" not found" then then ( ctype addr ) - swap to CType offset ; + else dup CDecl name sysdict @ find ?dup not if + CDecl name stype abort" not found" then then ( cdecl addr ) + swap to CDecl offset ; diff --git a/fs/comp/c/func.fs b/fs/comp/c/func.fs @@ -1,10 +1,10 @@ \ Function metadata ?f<< /comp/c/type.fs -0 value _curfunc \ ctype of the current function (includes arguments) -0 value _locvars \ the root ctype of local variables for current function +0 value _curfunc \ cdecl of the current function (includes arguments) +0 value _locvars \ the root cdecl of local variables for current function -: findIdent ( name -- ctype-or-0 ) - _curfunc if dup _curfunc CType :find ?dup if nip exit then then ( name ) - dup _locvars if to' _locvars CType :find else drop 0 then ( name ctype-or-0 ) +: findIdent ( name -- cdecl-or-0 ) + _curfunc if dup _curfunc CDecl :find ?dup if nip exit then then ( name ) + dup _locvars if to' _locvars CDecl :find else drop 0 then ( name cdecl-or-0 ) ?dup if nip else findSymbol then ; diff --git a/fs/comp/c/gen.fs b/fs/comp/c/gen.fs @@ -19,13 +19,13 @@ require /sys/scratch.fs : parseGlobalDecl ( ctype -- ) dup addSymbol - dup CType :static? not if \ not static - dup CType name NEXTWORD ! create then ( ctype ) - here over to CType offset ( ctype ) + dup CDecl :static? not if \ not static + dup CDecl name NEXTWORD ! create then ( ctype ) + here over to CDecl offset ( ctype ) '=' readChar? if ( ctype ) abort" TODO" - else to nexttputback dup CType :size allot then ( ctype ) + else to nexttputback dup CDecl :size allot then ( ctype ) ',' readChar? if - CType type parseDeclarator parseGlobalDecl + CDecl type parseDeclarator parseGlobalDecl else ';' expectChar drop then ; \ Begin parsing incoming tokens for a new "element" (a function or a @@ -38,12 +38,12 @@ require /sys/scratch.fs ';' readChar? if \ Only a type on a line is fine, carry on drop exit then to nexttputback parseDeclarator ( ctype ) - curstatic if dup CType :static! then + curstatic if dup CDecl :static! then _ccdebug if ." parsing: " dup printtype nl> then - dup CType :funcsig? if ( ctype ) + dup CDecl :funcsig? if ( ctype ) '{' readChar? if dup parseFunctionBody _ccdebug if - ." complete: " dup printtype nl> CType offset here over - spit nl> + ." complete: " dup printtype nl> CDecl offset here over - spit nl> else drop then else parseFunctionProto then else parseGlobalDecl then ( ) ; diff --git a/fs/comp/c/ptype.fs b/fs/comp/c/ptype.fs @@ -6,7 +6,7 @@ : _assert ( f -- ) not if _err then ; alias _err parseType ( tok -- type? f ) \ forward declaration -alias _err parseDeclarator ( type -- ctype ) \ forward declaration +alias _err parseDeclarator ( type -- cdecl ) \ forward declaration \ Parsing strategy: we dig down recursively through nextt until we get to our \ identifier. Before that identifier, we can hit chars like ( and *. @@ -14,74 +14,60 @@ alias _err parseDeclarator ( type -- ctype ) \ forward declaration \ recursion. \ After we hit the identifier, we continue parsing forward, where \ we can hit chars like [, an array specifier and (, a function specifier. We -\ process them, amending our ctype structure as we go. If we hit a ), we go up +\ process them, amending our cdecl structure as we go. If we hit a ), we go up \ one level in recursion and apply previously recorded indirection levels to the \ returned type. -: _arg ( parent-ctype tok -- offset ) - parseType _assert parseDeclarator ( ctype newtype ) - tuck swap to CType nexttype ( newtype ) - ')' readChar? if 0 swap CType :offset! else - ',' expectChar dup nextt _arg ( ctype offset ) - swap CType :offset! then ( offset ) ; +: _arg ( parent-cdecl tok -- offset ) + parseType _assert parseDeclarator ( cdecl newtype ) + tuck swap to CDecl nexttype ( newtype ) + ')' readChar? if 0 swap CDecl :offset! else + ',' expectChar dup nextt _arg ( cdecl offset ) + swap CDecl :offset! then ( offset ) ; \ parsing after the identifier -: _post ( ctype -- ctype ) - begin ( ctype ) nextt case +: _post ( cdecl -- cdecl ) + begin ( cdecl ) nextt case '[' of isChar?^ abort" TODO" endof '(' of isChar?^ - dup CType :funcsig! STORAGE_PS to@! curstorage >r - ')' readChar? not if ( ctype tok ) - over swap _arg ( ctype offset ) drop then + dup CDecl :funcsig! STORAGE_PS to@! curstorage >r + ')' readChar? not if ( cdecl tok ) + over swap _arg ( cdecl offset ) drop then r> to curstorage endof r> to nexttputback exit endcase again ; -: _addlvl ( lvl type -- type ) tuck type*lvl + dup 4 < _assert swap type*lvl! ; - -: _parseDeclarator ( type -- ctype ) +: _parseDeclarator ( type -- cdecl ) 0 begin ( type lvl ) '*' readChar? while ( type lvl tok ) 1+ repeat ( type lvl tok ) dup '(' isChar? if ( type lvl tok ) - drop swap parseDeclarator read) - >r >r \ V1=outer-ctype v2=inner-lvl - \ type recursion in C is "inside out". The ctype we have now is the outer - \ type. We'll forward its current "type" field to the ctype we're about to - \ finish parsing, and that new ctype will be placed in our outer type's - \ "type" field. One thing we have to be careful about is to keep our *lvl - \ where it belongs. - V1 CType type dup type*lvl ( inner-type outer-lvl ) - swap r> ( inner-lvl ) swap type*lvl! ( outer-lvl inner-type ) - NULLSTR swap CType :new _post ( outer-lvl inner-type ) - _addlvl ( inner-type ) r@ ( outer-type ) to CType type r> ( ctype ) + abort" TODO: declarator recursion" else ( type lvl tok ) dup isIdent? not if to nexttputback NULLSTR then ( type lvl name ) - rot CType :new ( lvl ctype ) - _post tuck CType type ( ctype lvl type ) - _addlvl ( ctype type ) - over to CType type ( ctype ) then ; + rot CDecl :new ( lvl cdecl ) tuck to CDecl lvl _post then ; current ' parseDeclarator realias -: _parseStruct ( -- ctype ) +: _parseStruct ( -- cdecl ) nextt dup isIdent? if nextt else NULLSTR swap then - '{' expectChar ( name ) TYPE_VOID CType :new ( res ) - dup CType :struct! dup addTypedef + '{' expectChar ( name ) TYPE_VOID CDecl :new ( res ) + dup CDecl :struct! dup addTypedef 0 >r dup begin ( res prev ) \ V1=offset '}' readChar? not while ( res prev tok ) parseType _assert parseDeclarator begin ( res prev new ) - tuck swap to CType nexttype ( res new ) - V1 over to CType offset + tuck swap to CDecl nexttype ( res new ) + V1 over to CDecl offset dup typesize to+ V1 ';' readChar? not while ( res prev tok ) - ',' expectChar dup CType type parseDeclarator repeat ( res prev ) + ',' expectChar dup CDecl type parseDeclarator repeat ( res prev ) repeat ( res prev ) rdrop drop ; \ parse a type from stream, starting with "tok". This only parses the "type" \ part without the "*" part or the name part. The result can be a "base" type -\ (type < $100) or a CType if the type is a struct, union or enum. -: _parseType ( tok -- type? f ) +\ (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> dup S" typedef" s= if - drop nextt parseType _assert parseDeclarator ( ctype ) + drop nextt parseType _assert parseDeclarator ( cdecl ) dup addTypedef 1 exit then dup S" struct" s= if drop _parseStruct 1 else dup S" unsigned" s= if drop $10 nextt else $00 swap then ( type tok ) diff --git a/fs/comp/c/type.fs b/fs/comp/c/type.fs @@ -24,72 +24,54 @@ Arena :new const _tarena \ Temporary alias _err _typesize ( type -- size-in-bytes ) alias _err _printtype ( type -- ) -\ All information related to a basic type fits in 1b, so that's how "type" is -\ passed around. Structure: -\ b1:0 = *lvl. Indirection levels, from 0 to 3. -\ b3:2 = size. 0=0 1=8 2=16 3=32 -\ b4 = sign. 0=signed 1=unsigned -\ b7:5 = reserved - -\ When a type is higher than $ff, it means that it's a pointer to a CType, +\ When a type is higher than $ff, it means that it's a pointer to a CDecl, \ which contains extra information needed for arrays (nbelem) and structs/sig -\ (offset and nexttype). All CType are aligned to 4 bytes, which allows our +\ (offset and nexttype). All CDecl are aligned to 4 bytes, which allows our \ pointers to use the lower 2 bits to be used for the "*lvl" field. -\ In the nomenclature below, "type" can be either a basic type or a CType, -\ but "ctype" is always a CType (which is also a type). +\ In the nomenclature below, "type" can be either a basic type or a CDecl, +\ but "cdecl" is always a CDecl (which is also a type). $0 const TYPE_VOID -$1 const TYPE_VOID* $4 const TYPE_CHAR -$5 const TYPE_CHAR* $8 const TYPE_SHORT -$9 const TYPE_SHORT* $c const TYPE_INT -$d const TYPE_INT* $1c const TYPE_UINT -$1d const TYPE_UINT* 0 const STORAGE_SF \ Stack frame 1 const STORAGE_PS \ Parameter Stack 2 const STORAGE_MEM \ Fixed address in memory -\ Set by pgen and determines the storage type of new created CTypes +\ Set by pgen and determines the storage type of new created CDecls STORAGE_MEM value curstorage 0 value curstatic \ is current definition "static"? : _arena curstorage STORAGE_MEM <> curstatic or if _tarena else _parena then ; 4 stringlist typenames "void" "char" "short" "int" -: type*lvl ( type -- lvl ) 3 and ; -\ TODO: have the _assert in type*lvl! it's not possible now because it breaks -\ the CC vms. -: type*lvl! ( lvl type -- type ) $fffffffc and or ; -: type*lvl+ ( type -- type ) dup type*lvl 1+ dup 4 < _assert swap type*lvl! ; -: type*lvl- ( type -- type ) dup type*lvl 1- dup 0>= _assert swap type*lvl! ; -create _ 0 c, 1 c, 2 c, 4 c, -: ctype? ( type -- f ) $ff > ; -: ctype' ( type -- ctype ) $fffffffc and ; - -\ CType flags -\ b0=is a struct? if 1, this is an "empty" ctype with the name of the struct. + +: cdecl? ( type -- f ) $ff > ; + +\ CDecl flags +\ b0=is a struct? if 1, this is an "empty" CDecl with the name of the struct. \ First field is nexttype. \ b1=is a funcsig? if 1, type is func return type and name is the name of the \ sig. arguments follow in nexttype. \ b2=has static storage? \ b3=incomplete? If 1, this is an incomplete definition. -struct[ CType - sfield nexttype \ a CType is a Linked List - sfield type \ a basic type. Can be a link to a CType +struct[ CDecl + sfield nexttype \ a CDecl is a Linked List + sfield type \ a basic type. Can be a link to a CDecl + sfield lvl \ indirection levels (*) sfield flags sfield offset \ offset, in bytes, of this element within its list - \ if this ctype is a function, offset contains its address. + \ if this cdecl is a function, offset contains its address. sfield nbelem \ number of elements in array. 0 if not an array. sfield storage \ one of the STORAGE_* consts SZ &+ name \ name associated with this type within its list. - : :new ( name type -- ctype ) + : :new ( name type -- cdecl ) $100 SZ + _arena Arena :[ - 0 align4 here rot> 0 , , 0 , 0 , 0 , curstorage , s, + 0 align4 here rot> 0 , , 0 , 0 , 0 , 0 , curstorage , s, _arena Arena :] drop ; : _f? doer , does> ( self 'w ) @ swap flags and bool ; @@ -98,10 +80,6 @@ struct[ CType 2 _f? :funcsig? 2 _f! :funcsig! 4 _f? :static? 4 _f! :static! 8 _f? :incomplete? 8 _f! :incomplete! - : :funcptr? - type dup ctype? if - dup type*lvl 1 = swap ctype' :funcsig? and - else drop 0 then ; : :isarg? ( dnode -- f ) storage STORAGE_PS = ; : :isglobal? ( dnode -- f ) storage STORAGE_MEM = ; @@ -114,23 +92,23 @@ struct[ CType \ Combined size of all fields in the LL. : :size ( self -- size ) dup :isarg? over :funcsig? or if drop CELLSZ exit then - 0 swap begin ( res ctype ) ?dup while + 0 swap begin ( res cdecl ) ?dup while tuck dup type _typesize swap nbelem 1 max * + swap llnext repeat ( res ) ; : :argssize ( self -- size ) dup :funcsig? _assert llcnt 1- CELLSZ * ; - : :type ( self -- type ) bi type | nbelem if type*lvl+ then ; : :offset! ( off self -- off+size ) 2dup to offset :size + ; - \ Find "name" in CType's LL. return 0 if not found + \ Find "name" in CDecl's LL. return 0 if not found : _ 2dup name s= not if llnext dup if _ then then ; - : :find ( name self -- ctype-or-0 ) llnext dup if _ then nip ; + : :find ( name self -- cdecl ) llnext dup if _ then nip ; : :find# :find dup _assert ; : _.children begin nexttype ?dup while dup _printtype ." , " repeat ; : :. ( self -- ) >r \ print without children r@ offset if '+' emit r@ offset .x? spc> then - r@ :struct? if ." struct" else r@ type _printtype then + r@ :struct? if ." struct" else + r@ type _printtype r@ lvl for '*' emit next then r@ name c@ if spc> r@ name stype then r@ nbelem if '[' emit r@ nbelem . ']' emit then r@ :funcsig? if '(' emit r@ _.children ')' emit then rdrop ; @@ -140,70 +118,50 @@ struct[ CType : :export ( self -- ) dup :struct? _assert \ we can only export structs - dup name NEXTWORD ! struct[ llnext begin ( ctype ) + dup name NEXTWORD ! struct[ llnext begin ( cdecl ) ?dup while - dup name NEXTWORD ! dup nbelem if ( ctype ) + dup name NEXTWORD ! dup nbelem if ( cdecl ) dup type _typesize over nbelem * sfield' - else ( ctype ) + else ( cdecl ) dup type _typesize case 1 of = sfieldb endof 2 of = sfieldw endof - sfield endcase then ( ctype ) + sfield endcase then ( cdecl ) llnext repeat ]struct ; : :append ( other self -- ) 2dup :size swap to offset llappend ; ]struct -: ensurebasetype ( type -- type ) - dup ctype? if ctype' CType type ensurebasetype then ; -: typeunsigned? ( type -- flags ) ensurebasetype 4 rshift 1 and ; - \ Typedefs are dictionary entries in the "typedefs" dicts, which contain a 4b \ value representing the type it aliases. create typedefs 0 , 0 c, \ this is a dict link -: addTypedef ( ctype -- ) typedefs over CType name entry , ; +: addTypedef ( cdecl -- ) typedefs over CDecl name entry , ; : findTypedef ( name -- type-or-0 ) typedefs find dup if @ then ; create _symbols 0 , 0 c, \ non-static create _ssymbols 0 , 0 c, \ static -: addSymbol ( ctype -- ) +: addSymbol ( cdecl -- ) curstatic if _ssymbols else _symbols then - over CType name dup c@ ( ctype 'dict name len ) + over CDecl name dup c@ ( cdecl 'dict name len ) ENTRYSZ + 8 + _arena Arena :[ entry , _arena Arena :] drop ; -: findSymbol ( name -- ctype-or-0 ) +: findSymbol ( name -- cdecl-or-0 ) dup _ssymbols find ?dup if nip @ else _symbols find dup if @ then then ; : cctypes$ 0 _ssymbols ! _tarena Arena :reset ; +: ensurebasetype ( type -- type ) + dup cdecl? if CDecl type ensurebasetype then ; +: typeunsigned? ( type -- flags ) ensurebasetype 4 rshift 1 and ; + : printtype ( type -- ) - dup ctype? if dup ctype' CType :. else + dup cdecl? if CDecl :. else dup typeunsigned? if ." unsigned " then - dup >> >> 3 and typenames slistiter stype then - type*lvl begin ?dup while '*' emit 1- repeat ; + >> >> 3 and typenames slistiter stype then ; current ' _printtype realias : typesize ( type -- size-in-bytes ) - dup type*lvl if drop 4 else - dup ctype? if - ctype' CType :size - else >> >> 3 and _ + c@ then then ; + dup cdecl? if + dup CDecl lvl if drop 4 else CDecl :size then + else >> >> 3 and _ + c@ then ; current ' _typesize realias - -: inttypeofsize ( size -- type ) case - 0 of = TYPE_VOID endof - 1 of = TYPE_CHAR endof - 2 of = TYPE_SHORT endof - 4 of = TYPE_INT endof - _err endcase ; - -\ Returns the "pointer arithmetics unit size" for type, that is, the size of -\ a "single element" in pointer arithmetics. This allows, for example, "ptr + 1" -\ to generate "ptr + 4" in native code if "ptr" is a "int*". -\ Pointers to pointers always return 4. Non-pointers always return 1. 1st level -\ pointers return the size of the data they point to. -: *ariunitsz ( type -- n ) dup type*lvl case - 0 of = drop 1 endof - 1 of = type*lvl- typesize endof - drop 4 - endcase ; diff --git a/fs/tests/comp/c/cc.fs b/fs/tests/comp/c/cc.fs @@ -30,9 +30,9 @@ ptrset 54 #eq 42 condif 142 #eq 42 incdec 43 #eq 54 incdecp 54 #eq -testend \s exprparens 9 #eq cnoop ( no result! ) scnt 0 #eq +testend \s 42 ptrari 50 #eq 42 50 ptrari2 2 #eq array 52 #eq diff --git a/fs/tests/comp/c/test2.c b/fs/tests/comp/c/test2.c @@ -119,3 +119,19 @@ int incdecp(int x) { x--; return x--; } +// test that parens override precedence +int exprparens() { + return (1 + 2) * 3; +} +// test that a void function doesn't add anything to PS +void cnoop() {} +// test that pointer arithmetics properly multiply operands by 2 or 4. +int* ptrari(int *x) { + cnoop(); // this doesn't mess up PS + x++; ++x; x--; + return x + 1; +} +// subtracting two pointers yield a number divided by the type size. +int ptrari2(int *lo, int *hi) { + return hi-lo; +}