diff options
-rw-r--r-- | cgen.c | 72 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 15 | ||||
-rw-r--r-- | types.h | 7 |
4 files changed, 67 insertions, 28 deletions
@@ -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"); @@ -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 @@ -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(); @@ -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 { |