From 7827280d96c975aff2b43dfb7b37d6e3c5ab7ad3 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 15 Jul 2020 00:28:42 -0400 Subject: fix struct definition generation order --- cgen.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- main.c | 1 - test.toc | 15 +++++++------- types.h | 7 ++++--- 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 { -- cgit v1.2.3