M fs/comp/c/ptype.fs => fs/comp/c/ptype.fs +10 -4
@@ 47,10 47,16 @@ alias _err parseDeclarator ( type -- cdecl ) \ forward declaration
0 begin ( type lvl )
'*' readChar? while ( type lvl tok ) 1+ repeat ( type lvl tok )
dup '(' isChar? if ( type lvl tok )
- drop swap _parseDeclarator read) ( lvl cdecl )
- \ type recursion in C is "inside out". The cdecl we have now is the result.
- \ We need to apply indirection levels we've already parsed to it.
- tuck to+ CDecl lvl
+ \ Complex type parsing is messed up. Example "int (*foo)[42]", a pointer to
+ \ an array of int (an array of int* is "int *foo[42]"). Right now, "type" is
+ \ "int" and we're about to parse the "(*foo)" part. This will give us a
+ \ CDecl {type=int,lvl=1,name=foo}. Now, for the _post part, we want a brand
+ \ new CDecl {type=int,lvl=0,nbelem=42,name=null}. Then, we set the first
+ \ CDecl's type to the newly parsed type. We have our "int (*foo)[42]".
+ \ The "lvl" we've just parsed above goes to the *inner* type.
+ drop over parseDeclarator read) ( type inner-lvl outer-type )
+ rot NULLSTR swap CDecl :new _post ( il ot inner-type )
+ rot over to CDecl lvl over to CDecl type ( cdecl )
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 ;
M fs/comp/c/type.fs => fs/comp/c/type.fs +1 -0
@@ 82,6 82,7 @@ struct[ CDecl
dup lvl if drop 0 else _ then ;
: :structarrow? ( self -- f ) \ is an indirect Struct reference?
dup lvl 1 = if _ else drop 0 then ;
+ : :funcptr? ( self -- f ) bi lvl 1 = | type :funcsig? and ;
: :constfuncsig? ( self -- f ) bi :funcsig? | :isglobal? and ;
\ Arrays, function signatures and struct ident "naturally" yield references.
M fs/tests/comp/c/type.fs => fs/tests/comp/c/type.fs +28 -28
@@ 55,41 55,41 @@ dup CDecl lvl 1 #eq
dup CDecl nbelem 42 #eq
CDecl name S" foo" #s=
-\ TODO: This test is not working. It's supposed to yield a pointer to an array
-\ of 42 ints, not an array of 42 pointers to ints.
-\ _parse int (*foo)[42] STOP
-\ dup CDecl type TYPE_INT #
-\ dup CDecl type lvl 1 #eq
-\ dup CDecl nbelem 0 #eq
-\ dup CDecl name S" foo" #s=
-\ CDecl type
-\ dup CDecl type TYPE_INT #eq
-\ dup CDecl nbelem 42 #eq
-\ CDecl name NULLSTR #s=
+_parse int (*foo)[42] STOP
+dup CDecl lvl 1 #eq
+dup CDecl nbelem 0 #eq
+dup CDecl name S" foo" #s=
+CDecl type
+ dup CDecl type TYPE_INT #eq
+ dup CDecl lvl 0 #eq
+ dup CDecl nbelem 42 #eq
+ CDecl name NULLSTR #s=
_parse unsigned int (*foo)(char,short) STOP
-dup CDecl :funcsig? #
+dup CDecl :funcptr? #
dup CDecl name S" foo" #s=
-dup CDecl type TYPE_UINT #eq
-CDecl args
-dup CDecl type TYPE_CHAR #eq
-dup CDecl offset 4 #eq \ PS args are always 4b in size
-llnext
-dup CDecl type TYPE_SHORT #eq
-CDecl offset 0 #eq
+CDecl type
+ dup CDecl type TYPE_UINT #eq
+ CDecl args
+ dup CDecl type TYPE_CHAR #eq
+ dup CDecl offset 4 #eq \ PS args are always 4b in size
+ llnext
+ dup CDecl type TYPE_SHORT #eq
+ CDecl offset 0 #eq
\ We can also have a function signature with argument names.
_parse unsigned int (*foo)(short bar,char baz) STOP
-dup CDecl :funcsig? #
+dup CDecl :funcptr? #
dup CDecl name S" foo" #s=
-CDecl args
-dup CDecl name S" bar" #s=
-dup CDecl type TYPE_SHORT #eq
-dup CDecl offset 4 #eq
-llnext
-dup CDecl name S" baz" #s=
-dup CDecl type TYPE_CHAR #eq
-CDecl offset 0 #eq
+CDecl type
+ CDecl args
+ dup CDecl name S" bar" #s=
+ dup CDecl type TYPE_SHORT #eq
+ dup CDecl offset 4 #eq
+ llnext
+ dup CDecl name S" baz" #s=
+ dup CDecl type TYPE_CHAR #eq
+ CDecl offset 0 #eq
_parse Struct1 *mystructptr STOP
capture printtype