commit d5f09b142346dbaa28e4614dfef045719acdd3f3
parent 784096f1a54f903890fec5c8ae73278e33664fdc
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Tue, 4 Oct 2022 10:14:49 -0400
cc: add function signature type
Diffstat:
10 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/fs/app/cos/cvm.c b/fs/app/cos/cvm.c
@@ -1,5 +1,4 @@
// This doesn't compile. It's a prototype of what it will look like.
-// TODO: function pointer arrays (iord iowr).
// TODO: %s %x (4b hex) %w (2b hex) %b (1b hex) formatting
// TODO: NULL
// TODO: typecasting studs (we don't have a checker yet, but support the syntax)
diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs
@@ -508,8 +508,8 @@ current to parseStatement
0 to curstatic
dup S" static" s= if drop nextt 1 to curstatic then
dup S" typedef" s= if
- drop nextt parseType _assert
- nextt expectIdent read; addTypedef drop exit then
+ drop nextt parseType _assert parseVariable ( ctype )
+ read; addTypedef drop exit then
parseType _assert ( unode type )
nextt dup ';' isChar? if \ Only a type on a line is fine, carry on
2drop drop exit then
diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs
@@ -213,7 +213,8 @@ ASTIDCNT wordtbl gentbl ( node -- )
0 to lastidentfound
dup Node firstchild gennode \ op has call address
lastidentfound ?dup if
- dup Node id AST_FUNCTION = if Function :rettype else drop TYPE_VOID then
+ dup Node id AST_FUNCTION = if Function :rettype
+ else Declare ctype CType type dup CType :funcsig? _assert CType type then
else
vmop loc VM_*CONSTANT = if vmop arg wordfunctype else TYPE_VOID then then
( node type ) vmop :push rot ( type 'copy node )
diff --git a/fs/cc/type.fs b/fs/cc/type.fs
@@ -67,6 +67,8 @@ struct[ CType
sfield type \ a basic type. Can be a link to a CType
sfield flags \ b0=is a struct? if 1, this is an "empty" ctype 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.
sfield offset \ offset, in bytes, of this element within its list
sfield nbelem \ number of elements in array. 0 if not an array.
sfield storage \ one of the STORAGE_* consts
@@ -76,6 +78,7 @@ struct[ CType
0 align4 here rot> 0 , , 0 , 0 , 0 , STORAGE_SF , s, ;
: :struct? flags 1 and ;
+ : :funcsig? flags 2 and ;
: :isarg? ( dnode -- f ) storage STORAGE_PS = ;
: :isglobal? ( dnode -- f ) storage STORAGE_MEM = ;
@@ -95,21 +98,24 @@ struct[ CType
: _ 2dup name s= if nip else llnext ?dup if _ else _err then then ;
: :find ( name self -- ctype ) llnext _ ;
+ : _( case of :struct? ." {" endof
+ of :funcsig? ." (" endof
+ r@ nexttype if ." , " then endcase ;
+ : _) case of :struct? ." }" endof of :funcsig? ." )" endof endcase ;
: :. ( self -- ) >r
r@ offset if '+' emit r@ offset .x? spc> then
r@ :struct? if ." struct" else r@ type _printtype then
r@ name c@ if spc> r@ name stype then
r@ nbelem if '[' emit r@ nbelem . ']' emit then
- r@ :struct? if ." { " r@ nexttype ?dup if :. then ." }"
- else r@ nexttype ?dup if ." , " :. then
- then rdrop ;
+ r@ _( r@ nexttype ?dup if :. then r@ _) rdrop ;
]struct
\ Typedefs are dictionary entries in the "typedefs" dict, which contains a 4b
\ value representing the type it aliases.
create typedefs 0 , 0 c, \ this is a dict link
-: addTypedef ( type name -- ) typedefs swap entry , ;
+: addTypedef ( ctype -- ) typedefs over CType name entry
+ dup CType flags not if CType type then , ;
: findTypedef ( name -- type-or-0 ) typedefs find dup if @ then ;
: cctypes$ 0 typedefs ! ;
@@ -138,10 +144,20 @@ current to _typesize
: parseType* ( type -- type tok )
begin nextt dup '*' isChar? while drop type*lvl+ repeat ;
+: parseFuncSig ( type -- ctype )
+ nextt '*' expectChar nextt expectIdent ( type name )
+ swap CType :new ( ctype )
+ 2 over to CType flags ( ctype )
+ nextt ')' expectChar nextt '(' expectChar begin ( ctype )
+ \ TODO: don't ignore funcsig arguments
+ nextt dup ')' isChar? not while ( ctype tok ) drop
+ repeat ( ctype tok ) drop ;
+
\ Given a "type" part that is already parsed from parseType, parse the rest of
\ a variable declaration, that is, the indirections (*), the name and nbelem
\ ([]). This always returns a CType.
: parseVariable ( type -- ctype )
+ nextt dup '(' isChar? if drop parseFuncSig exit else to nexttputback then
parseType* expectIdent swap CType :new ( ctype )
nextt dup S" [" s= if ( ctype tok )
drop nextt parse _assert nextt ']' expectChar ( ctype nbelem )
@@ -155,8 +171,9 @@ current to _typesize
dup S" struct" s= if
drop nextt dup isIdent? if nextt else NULLSTR swap then
'{' expectChar ( name ) TYPE_VOID CType :new ( res )
- dup CType name c@ if dup dup CType name addTypedef then
- 1 over to CType flags 0 >r dup begin ( res prev ) \ V1=offset
+ 1 over to CType flags
+ dup CType name c@ if dup addTypedef then
+ 0 >r dup begin ( res prev ) \ V1=offset
nextt dup '}' isChar? not while ( res prev tok )
parseType _assert parseVariable ( res prev new )
tuck swap to CType nexttype ( res new )
diff --git a/fs/cc/vm/commonlo.fs b/fs/cc/vm/commonlo.fs
@@ -92,16 +92,14 @@ vmop :self to vmop^ other
\ Managing operands
-: hasop# vmop :hasop# ;
-: isconst? vmop :isconst? ;
-: isconst# isconst? _assert ;
-: noop# vmop :noop# ;
+: isconst# vmop :isconst? _assert ;
: const>op ( n -- ) vmop :>const ;
-: constarray>op ( a -- ) noop# VM_CONSTARRAY to vmop loc to vmop arg ;
-: sf+>op ( off -- ) noop# VM_*STACKFRAME to vmop loc to vmop arg ;
-: ps+>op ( off -- ) noop# VM_*ARGSFRAME to vmop loc to vmop arg ;
-: mem>op ( n -- ) noop# VM_*CONSTANT to vmop loc to vmop arg ;
+: constarray>op ( a -- ) vmop :noop# VM_CONSTARRAY to vmop loc to vmop arg ;
+: sf+>op ( off -- ) vmop :noop# VM_*STACKFRAME to vmop loc to vmop arg ;
+: ps+>op ( off -- ) vmop :noop# VM_*ARGSFRAME to vmop loc to vmop arg ;
+: mem>op ( n -- ) vmop :noop# VM_*CONSTANT to vmop loc to vmop arg ;
: ctype>op ( ctype -- )
+ vmop :noop#
dup CType type to vmop type ( ctype )
case
of CType :isglobal? r@ CType offset mem>op endof
diff --git a/fs/cc/vm/forth.fs b/fs/cc/vm/forth.fs
@@ -111,7 +111,7 @@ struct+[ VMOp
0 to psoff ;
\ Allocate a new register for active op and pop 4b from PS into it.
-: vmpspop, noop# vmop :>TOS PS+ vmop :>reg ;
+: vmpspop, vmop :noop# vmop :>TOS PS+ vmop :>reg ;
\ Push active op to PS.
: vmpspush, vmop :compile vmop :forgetTOS PS- ;
diff --git a/fs/cc/vm/i386.fs b/fs/cc/vm/i386.fs
@@ -130,7 +130,7 @@ struct+[ VMOp
\ Allocate a new register for active op and pop 4b from PS into it.
: vmpspop,
- noop# VM_REGISTER to vmop loc regallot dup to vmop arg r! bp 0 d) mov,
+ vmop :noop# VM_REGISTER to vmop loc regallot dup to vmop arg r! bp 0 d) mov,
bp CELLSZ i) add, ;
\ Push active op to PS.
diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs
@@ -35,6 +35,7 @@ global 1234 #eq
globalinc 1236 #eq
globalinc 1238 #eq
42 142 sysword 142 #eq
+42 142 funcsig 142 #eq
capture helloworld S" Hello World!" #s=
42 40 50 isinrange 1 #eq
42 30 40 isinrange 0 #eq
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -140,6 +140,14 @@ int globalinc() {
int sysword(int a, int b) {
return max(a, b);
}
+
+typedef unsigned int (*MaxSig)(unsigned int, unsigned int);
+// Same as above, but through a function signature typedef
+int funcsig(int a, int b) {
+ MaxSig fn = &max;
+ return fn(a, b);
+}
+
void helloworld() {
stype("Hello World!");
}
@@ -218,6 +226,8 @@ int unaryopmut(int n) {
}
typedef short MyType;
+typedef MyType** MyTypePtr;
+
struct MyStruct {
int foo;
MyType bar;
diff --git a/fs/tests/cc/type.fs b/fs/tests/cc/type.fs
@@ -32,7 +32,7 @@ S" bar" over CType :find
\ once defined, parseType will find the struct in typedefs
current with-stdin< Struct1 STOP over #eq
capture printtype
-S" struct Struct1 { unsigned int foo, +04 short* bar, +08 char baz[2] }" #s=
+S" struct Struct1 {unsigned int foo, +04 short* bar, +08 char baz[2]}" #s=
\ Anonymous structs work too
current with-stdin< struct { int foo; } STOP typesize 4 #eq