summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c72
-rw-r--r--main.c1
-rw-r--r--test.toc15
-rw-r--r--types.h7
4 files changed, 67 insertions, 28 deletions
diff --git a/cgen.c b/cgen.c
index 6c03065..2ff424c 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1974,6 +1974,61 @@ static void cgen_global_decl(CGenerator *g, Declaration *d) {
}
}
+// this complicated stuff is necessary so that the order of the struct definitions is correct.
+// for example, if we have
+// a ::= struct { x: [5]b; }
+// b ::= struct { foo: int; }
+// we need b to be generated before a
+
+static void cgen_struct_def(CGenerator *g, StructDef *sdef);
+
+static void cgen_struct_defs_needed_by_type(CGenerator *g, Type *t) {
+ switch (t->kind) {
+ case TYPE_STRUCT:
+ cgen_struct_def(g, t->struc);
+ break;
+ case TYPE_ARR:
+ cgen_struct_defs_needed_by_type(g, t->arr->of);
+ break;
+ case TYPE_FN:
+ case TYPE_SLICE:
+ case TYPE_PTR:
+ case TYPE_BUILTIN:
+ break;
+ case TYPE_TUPLE:
+ case TYPE_UNKNOWN:
+ case TYPE_EXPR:
+ assert(0);
+ break;
+ }
+}
+
+static void cgen_struct_def(CGenerator *g, StructDef *sdef) {
+ assert(sdef->flags & STRUCT_DEF_RESOLVED);
+ if (sdef->flags & STRUCT_DEF_CGENERATED) {
+ return;
+ }
+ sdef->flags |= STRUCT_DEF_CGENERATED;
+ arr_foreach(sdef->fields, Field, field)
+ cgen_struct_defs_needed_by_type(g, field->type);
+ cgen_write(g, "struct ");
+ cgen_struct_name(g, sdef);
+ cgen_write(g, "{");
+ cgen_nl(g);
+ ++g->indent_lvl;
+ arr_foreach(sdef->fields, Field, field) {
+ cgen_type_pre(g, field->type);
+ cgen_write(g, " ");
+ cgen_ident_simple(g, field->name);
+ cgen_type_post(g, field->type);
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ --g->indent_lvl;
+ cgen_write(g, "};");
+ cgen_nl(g);
+}
+
static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
g->block = NULL;
g->nms = NULL;
@@ -2032,22 +2087,7 @@ static void cgen_file(CGenerator *g, ParsedFile *f, Typer *tr) {
// struct definitions
arr_foreach(tr->all_structs, StructDefPtr, sdefp) {
StructDef *sdef = *sdefp;
- cgen_write(g, "struct ");
- cgen_struct_name(g, sdef);
- cgen_write(g, "{");
- cgen_nl(g);
- ++g->indent_lvl;
- arr_foreach(sdef->fields, Field, field) {
- cgen_type_pre(g, field->type);
- cgen_write(g, " ");
- cgen_ident_simple(g, field->name);
- cgen_type_post(g, field->type);
- cgen_write(g, ";");
- cgen_nl(g);
- }
- --g->indent_lvl;
- cgen_write(g, "};");
- cgen_nl(g);
+ cgen_struct_def(g, sdef);
}
cgen_write(g, "/* declarations */\n");
diff --git a/main.c b/main.c
index 0a75e61..7455951 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
see development.md for development information
@TODO:
-see todo in test.toc
see note in types.c : we probably shouldn't go to the trouble of evaluating this (just do this stuff if it's an ident)
ensure that in s[a:b] s is an l-value if it's an array
make sure you can't pass a function template or a tuple to varargs
diff --git a/test.toc b/test.toc
index 37f63f7..ade7c93 100644
--- a/test.toc
+++ b/test.toc
@@ -122,14 +122,6 @@ some_fn ::= fn(a,b,c: int, d,e,f := 3.0) y : f64 = 3.111 {
}
main ::= fn() {
- // @TODO: moving this to the bottom of main screws up the order the structs are generated in.
- Point2D ::= struct {
- x, y : int;
- }
- Point ::= struct {
- use p: Point2D;
- z: float;
- }
foo0 := int == int;
bar0 := int == float;
foo1 := &&&int == &&&u8;
@@ -162,5 +154,12 @@ main ::= fn() {
xx ::= fn() (int, int) {
return 3, 5;
}
+ Point2D ::= struct {
+ x, y : int;
+ }
+ Point ::= struct {
+ use p: Point2D;
+ z: float;
+ }
}
main();
diff --git a/types.h b/types.h
index bca892d..99648ad 100644
--- a/types.h
+++ b/types.h
@@ -513,9 +513,10 @@ typedef Block *BlockPtr;
enum {
STRUCT_DEF_FOUND_OFFSETS = 0x01,
- STRUCT_DEF_RESOLVED = 0x10,
- STRUCT_DEF_RESOLVING = 0x20,
- STRUCT_DEF_RESOLVING_FAILED = 0x40
+ STRUCT_DEF_CGENERATED = 0x02,
+ STRUCT_DEF_RESOLVED = 0x04,
+ STRUCT_DEF_RESOLVING = 0x08,
+ STRUCT_DEF_RESOLVING_FAILED = 0x10
};
typedef U8 StructFlags;
typedef struct StructDef {