diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-06 16:43:55 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-06 16:43:55 -0500 |
commit | 0e203bce341829d8761176c5f6763a0523a610cf (patch) | |
tree | 5444526e3a19e54d85dc7331b79c85d2a228444c | |
parent | 24e96d9dda5387203322abc28fa875f8579a7c19 (diff) |
fixed bug with cgen structs
-rw-r--r-- | cgen.c | 12 | ||||
-rw-r--r-- | copy.c | 7 | ||||
-rw-r--r-- | decls_cgen.c | 70 | ||||
-rw-r--r-- | eval.c | 34 | ||||
-rw-r--r-- | identifiers.c | 1 | ||||
-rw-r--r-- | instance_table.c | 6 | ||||
-rw-r--r-- | package.c | 7 | ||||
-rw-r--r-- | parse.c | 8 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | typedefs_cgen.c | 103 | ||||
-rw-r--r-- | types.c | 35 | ||||
-rw-r--r-- | types.h | 12 |
12 files changed, 209 insertions, 88 deletions
@@ -5,7 +5,7 @@ */ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev, Allocator *allocr) { g->outc = out; - g->ident_counter = 1; /* some places use 0 to mean no id */ + g->ident_counter = 0; g->main_ident = ident_get(ids, "main"); g->evalr = ev; g->will_indent = true; @@ -760,7 +760,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { case EXPR_WHILE: case EXPR_EACH: case EXPR_BLOCK: { - id = g->ident_counter++; + id = ++g->ident_counter; cgen_ident_id_to_str(ret_name, id); char *p = ret_name + strlen(ret_name); @@ -1026,7 +1026,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { } if (cgen_uses_ptr(&e->type) && e->type.kind != TYPE_TUPLE) { - e->call.c.id = g->ident_counter++; + e->call.c.id = ++g->ident_counter; if (!cgen_type_pre(g, &e->type, e->where)) return false; cgen_write(g, " "); cgen_ident_id(g, e->call.c.id); @@ -1070,8 +1070,8 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { break; case EXPR_SLICE: { SliceExpr *s = &e->slice; - IdentID s_id = e->slice.c.id = g->ident_counter++; - IdentID from_id = g->ident_counter++; + IdentID s_id = e->slice.c.id = ++g->ident_counter; + IdentID from_id = ++g->ident_counter; if (!cgen_expr_pre(g, s->of)) return false; if (s->from && !cgen_expr_pre(g, s->from)) @@ -1135,7 +1135,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { if (!cgen_val_pre(g, e->val, &e->type, e->where)) return false; if (!cgen_type_pre(g, &e->type, e->where)) return false; - e->val_c_id = g->ident_counter++; + e->val_c_id = ++g->ident_counter; cgen_write(g, " "); cgen_ident_id(g, e->val_c_id); if (!cgen_type_post(g, &e->type, e->where)) return false; @@ -38,6 +38,8 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { case TYPE_SLICE: case TYPE_VOID: case TYPE_UNKNOWN: + case TYPE_PKG: + case TYPE_TYPE: *out = *in; break; case TYPE_ARR: { @@ -55,9 +57,6 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { out->struc = allocr_malloc(a, bytes); memcpy(out->struc, in->struc, bytes); } break; - case TYPE_TYPE: - *out = *in; - break; case TYPE_EXPR: assert(0); } @@ -268,7 +267,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { copy_expr(c, sout->to = allocr_malloc(a, sizeof *sout->to), sin->to); } break; case EXPR_PKG: - copy_expr(c, out->pkg.name = allocr_malloc(a, sizeof *out->pkg.name), in->pkg.name); + copy_expr(c, out->pkg.name_expr = allocr_malloc(a, sizeof *out->pkg.name_expr), in->pkg.name_expr); break; case EXPR_TYPE: copy_type(c, &out->typeval, &in->typeval); diff --git a/decls_cgen.c b/decls_cgen.c index 94e65df..85c574c 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -7,6 +7,41 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s); static bool cgen_decls_block(CGenerator *g, Block *b); static bool cgen_decls_decl(CGenerator *g, Declaration *d); +static bool cgen_decls_type(CGenerator *g, Type *type, Location where) { + if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */ + return true; + if (type->kind == TYPE_STRUCT) { + StructDef *sdef = type->struc; + if (!(sdef->flags & STRUCT_DEF_CGENERATED)) { + /* generate struct definition */ + cgen_write(g, "struct "); + if (sdef->c.name) { + cgen_ident(g, sdef->c.name); + } else { + assert(sdef->c.id); + cgen_ident_id(g, sdef->c.id); + } + cgen_write(g, "{"); + cgen_nl(g); + ++g->indent_lvl; + arr_foreach(sdef->fields, Field, f) { + if (!cgen_type_pre(g, f->type, where)) return false; + cgen_write(g, " "); + cgen_ident(g, f->name); + if (!cgen_type_post(g, f->type, where)) return false; + cgen_write(g, ";"); + cgen_nl(g); + } + --g->indent_lvl; + cgen_write(g, "};"); + cgen_nl(g); + sdef->flags |= STRUCT_DEF_CGENERATED; + } + } + cgen_recurse_into_type(cgen_decls_type, g, type, where); + return true; +} + static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) { if (cgen_should_gen_fn(f)) { if (!fn_enter(f, 0)) @@ -57,7 +92,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { FnExpr *f = e->fn; f->c.name = NULL; if (!f->c.id) - f->c.id = g->ident_counter++; + f->c.id = ++g->ident_counter; FnType *fn_type = &e->type.fn; if (fn_type->constness) { if (!cgen_decls_fn_instances(g, e)) @@ -69,33 +104,12 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { } break; case EXPR_TYPE: { Type *type = &e->typeval; - if (type->kind == TYPE_STRUCT) { - StructDef *sdef = type->struc; - if (!(sdef->flags & STRUCT_DEF_CGENERATED)) { - /* generate struct definition */ - cgen_write(g, "struct "); - if (sdef->c.name) - cgen_ident(g, sdef->c.name); - else - cgen_ident_id(g, sdef->c.id); - cgen_write(g, "{"); - cgen_nl(g); - ++g->indent_lvl; - arr_foreach(sdef->fields, Field, f) { - if (!cgen_type_pre(g, f->type, e->where)) return false; - cgen_write(g, " "); - cgen_ident(g, f->name); - if (!cgen_type_post(g, f->type, e->where)) return false; - cgen_write(g, ";"); - cgen_nl(g); - } - --g->indent_lvl; - cgen_write(g, "};"); - cgen_nl(g); - sdef->flags |= STRUCT_DEF_CGENERATED; - } - } + if (!cgen_decls_type(g, type, e->where)) + return false; } break; + case EXPR_CAST: + if (!cgen_decls_type(g, &e->cast.type, e->where)) + return false; default: break; } @@ -117,6 +131,8 @@ static bool cgen_decls_block(CGenerator *g, Block *b) { } static bool cgen_decls_decl(CGenerator *g, Declaration *d) { + if (!cgen_decls_type(g, &d->type, d->where)) + return false; if (cgen_fn_is_direct(g, d)) { d->expr.fn->c.name = d->idents[0]; if (d->expr.type.fn.constness) { @@ -56,6 +56,7 @@ static size_t compiler_sizeof_builtin(BuiltinType b) { } static size_t compiler_alignof(Type *t) { + Value v; assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: @@ -63,11 +64,11 @@ static size_t compiler_alignof(Type *t) { case TYPE_VOID: return 1; case TYPE_FN: - return sizeof(FnExpr *); + return sizeof v.fn; case TYPE_PTR: - return sizeof(void *); + return sizeof v.ptr; case TYPE_TUPLE: - return sizeof(Value *); + return sizeof v.tuple; case TYPE_ARR: return compiler_alignof(t->arr.of); case TYPE_SLICE: @@ -76,7 +77,9 @@ static size_t compiler_alignof(Type *t) { else return sizeof(size_t); case TYPE_TYPE: - return sizeof(Type *); + return sizeof v.type; + case TYPE_PKG: + return sizeof v.pkg; case TYPE_STRUCT: { /* assume the align of a struct is (at most) the greatest align out of its children's */ size_t align = 1; @@ -118,22 +121,25 @@ static void eval_struct_find_offsets(Type *t) { /* size of a type at compile time */ static size_t compiler_sizeof(Type *t) { + Value v; assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: return compiler_sizeof_builtin(t->builtin); case TYPE_FN: - return sizeof(FnExpr *); + return sizeof v.fn; case TYPE_PTR: - return sizeof(void *); + return sizeof v.ptr; case TYPE_ARR: return t->arr.n * compiler_sizeof(t->arr.of); case TYPE_TUPLE: - return sizeof(Value *); + return sizeof v.tuple; case TYPE_SLICE: - return sizeof(Slice); + return sizeof v.slice; case TYPE_TYPE: - return sizeof(Type *); + return sizeof v.type; + case TYPE_PKG: + return sizeof v.pkg; case TYPE_STRUCT: { eval_struct_find_offsets(t); return t->struc->size; @@ -318,6 +324,10 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { case TYPE_PTR: fprintf(f, "<pointer: %p>", *(void **)p); break; + case TYPE_PKG: { + Package *pkg = *(Package **)p; + fprintf(f, "<package at %p>", (void *)pkg); + } break; case TYPE_SLICE: { fprintf(f, "["); /* TODO: change? when slice initializers are added */ Slice slice = *(Slice *)p; @@ -614,6 +624,9 @@ static void eval_deref(Value *v, void *ptr, Type *type) { case TYPE_TYPE: v->type = *(Type **)ptr; break; + case TYPE_PKG: + v->pkg = *(Package **)ptr; + break; case TYPE_VOID: case TYPE_UNKNOWN: case TYPE_EXPR: @@ -652,6 +665,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) { case TYPE_TYPE: *(Type **)set = to->type; break; + case TYPE_PKG: + *(Package **)set = to->pkg; + break; case TYPE_VOID: case TYPE_UNKNOWN: case TYPE_EXPR: diff --git a/identifiers.c b/identifiers.c index a7750a7..3bb3eb1 100644 --- a/identifiers.c +++ b/identifiers.c @@ -36,6 +36,7 @@ static Identifier ident_new(Identifiers *ids, Identifier parent, unsigned char i for (size_t i = 0; i < TREE_NCHILDREN; ++i) tree->children[i] = NULL; tree->decls = NULL; + tree->pkg = NULL; #endif tree->parent = parent; if (parent) diff --git a/instance_table.c b/instance_table.c index 3c859ac..aeb72d3 100644 --- a/instance_table.c +++ b/instance_table.c @@ -191,6 +191,10 @@ static U64 val_ptr_hash(void *v, Type *t) { } return hash; } + case TYPE_PKG: { + Package *pkg = *(Package **)v; + return (U64)pkg; + } break; case TYPE_EXPR: break; } assert(0); @@ -272,6 +276,8 @@ static bool val_ptr_eq(void *u, void *v, Type *t) { return false; } return true; + case TYPE_PKG: + return *(Package **)u == *(Package **)v; case TYPE_EXPR: break; } assert(0); @@ -261,6 +261,10 @@ static bool export_val_ptr(Exporter *ex, void *val, Type *type, Location where) if (!export_fn_ptr(ex, *(FnExpr **)val, where)) return false; break; + case TYPE_PKG: { + Package *pkg = *(Package **)val; + export_ident(ex, pkg->name); + } break; case TYPE_UNKNOWN: case TYPE_EXPR: assert(0); @@ -406,8 +410,7 @@ static bool export_expr(Exporter *ex, Expression *e) { return false; } break; case EXPR_PKG: - if (!export_expr(ex, e->pkg.name)) - return false; + export_ident(ex, e->pkg.name_ident); break; case EXPR_SLICE: { SliceExpr *s = &e->slice; @@ -1013,7 +1013,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_PKG: ++t->token; e->kind = EXPR_PKG; - if (!parse_expr(p, e->pkg.name = parser_malloc(p, sizeof *e->pkg.name), expr_find_end(p, 0))) + if (!parse_expr(p, e->pkg.name_expr = parser_malloc(p, sizeof *e->pkg.name_expr), expr_find_end(p, 0))) return false; return true; case KW_FN: { @@ -2236,7 +2236,11 @@ static void fprint_expr(FILE *out, Expression *e) { break; case EXPR_PKG: fprintf(out, "(pkg "); - fprint_expr(out, e->pkg.name); + if (found_type) { + fprint_ident(out, e->pkg.name_ident); + } else { + fprint_expr(out, e->pkg.name_expr); + } fprintf(out, ")"); break; } @@ -17,4 +17,6 @@ main ::= fn() { puti(a); puti(b); c:x = 7; d:x = 18; + k : [5]struct {x: int; y: int;}; + puti(k[0].x); };
\ No newline at end of file diff --git a/typedefs_cgen.c b/typedefs_cgen.c index 3050409..531fb0d 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -7,6 +7,75 @@ static bool typedefs_stmt(CGenerator *g, Statement *s); static bool typedefs_decl(CGenerator *g, Declaration *d); static bool typedefs_expr(CGenerator *g, Expression *e); +#define cgen_recurse_into_type(f, g, type, extra) \ + switch (type->kind) { \ + case TYPE_STRUCT: \ + arr_foreach(type->struc->fields, Field, fl) \ + if (!f(g, fl->type, extra)) \ + return false; \ + break; \ + case TYPE_FN: \ + arr_foreach(type->fn.types, Type, sub) { \ + if (!f(g, sub, extra)) \ + return false; \ + } \ + break; \ + case TYPE_TUPLE: \ + arr_foreach(type->tuple, Type, sub) \ + if (!f(g, sub, extra)) \ + return false; \ + break; \ + case TYPE_ARR: \ + if (!f(g, type->arr.of, extra)) \ + return false; \ + break; \ + case TYPE_SLICE: \ + if (!f(g, type->slice, extra)) \ + return false; \ + break; \ + case TYPE_PTR: \ + if (!f(g, type->ptr, extra)) \ + return false; \ + break; \ + case TYPE_VOID: \ + case TYPE_BUILTIN: \ + case TYPE_PKG: \ + case TYPE_TYPE: \ + case TYPE_UNKNOWN: \ + break; \ + case TYPE_EXPR: assert(0); \ + } + + +/* i is the name for this type, NULL if not available */ +/* ALWAYS RETURNS TRUE. it just returns a bool for cgen_recurse_into_type to work */ +static bool typedefs_type(CGenerator *g, Type *type, Identifier i) { + if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */ + return true; + if (type->kind == TYPE_STRUCT) { + StructDef *sdef = type->struc; + /* we'll actually define the struct later; here we can just declare it */ + + if (sdef->c.id || sdef->c.name) { + /* we've already done this */ + } else { + cgen_write(g, "struct "); + if (i) { + cgen_ident(g, i); + sdef->c.name = i; + } else { + IdentID id = ++g->ident_counter; + cgen_ident_id(g, id); + sdef->c.id = id; + } + cgen_write(g, ";"); + cgen_nl(g); + } + } + cgen_recurse_into_type(typedefs_type, g, type, NULL); + return true; +} + static bool typedefs_block(CGenerator *g, Block *b) { Block *prev = g->block; if (!cgen_block_enter(g, b)) @@ -22,9 +91,12 @@ static bool typedefs_block(CGenerator *g, Block *b) { static bool typedefs_expr(CGenerator *g, Expression *e) { cgen_recurse_subexprs(g, e, typedefs_expr, typedefs_block, typedefs_decl); + if (e->kind == EXPR_CAST) { + typedefs_type(g, &e->cast.type, NULL); + } if (e->kind == EXPR_FN) { /* needs to go before decls_cgen.c... */ - e->fn->c.id = g->ident_counter++; + e->fn->c.id = ++g->ident_counter; } if (e->kind == EXPR_TYPE && e->typeval.kind == TYPE_STRUCT) { StructDef *sdef = e->typeval.struc; @@ -32,7 +104,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) { /* we've already done this */ } else { cgen_write(g, "struct "); - IdentID id = g->ident_counter++; + IdentID id = ++g->ident_counter; cgen_ident_id(g, id); sdef->c.id = id; cgen_write(g, ";"); @@ -43,6 +115,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) { } static bool typedefs_decl(CGenerator *g, Declaration *d) { + typedefs_type(g, &d->type, NULL); if (cgen_fn_is_direct(g, d)) { d->expr.fn->c.name = d->idents[0]; } @@ -52,26 +125,12 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) { Value *val = decl_val_at_index(d, idx); if (type->kind == TYPE_TYPE) { /* generate typedef */ - IdentID id = 0; - if (g->block != NULL || g->fn != NULL) - id = g->ident_counter++; - if (val->type->kind == TYPE_STRUCT) { - /* we'll actually define the struct later; here we can just declare it */ - StructDef *sdef = val->type->struc; - if (sdef->c.id || sdef->c.name) { - /* we've already done this */ - } else { - cgen_write(g, "struct "); - if (id) { - cgen_ident_id(g, id); - sdef->c.id = id; - } else { - cgen_ident(g, i); - sdef->c.name = i; - } - cgen_write(g, ";"); - } - } else { + typedefs_type(g, val->type, i); + + if (val->type->kind != TYPE_STRUCT) { + IdentID id = 0; + if (g->block != NULL || g->fn != NULL) + id = ++g->ident_counter; if (val->type->kind != TYPE_TYPE) { cgen_write(g, "typedef "); if (!cgen_type_pre(g, val->type, d->where)) return false; @@ -7,6 +7,7 @@ static bool types_stmt(Typer *tr, Statement *s); static bool types_block(Typer *tr, Block *b); static bool type_resolve(Typer *tr, Type *t, Location where); + static inline void *typer_malloc(Typer *tr, size_t bytes) { return allocr_malloc(tr->allocr, bytes); } @@ -23,6 +24,10 @@ static inline bool type_is_builtin(Type *t, BuiltinType b) { return t->kind == TYPE_BUILTIN && t->builtin == b; } +static inline bool type_is_slicechar(Type *t) { + return t->kind == TYPE_SLICE && type_is_builtin(t->slice, BUILTIN_CHAR); +} + #define typer_arr_add(tr, a) typer_arr_add_(tr, (void **)(a), sizeof **(a)) static bool type_eq(Type *a, Type *b) { @@ -826,7 +831,7 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_LITERAL_INT: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_I64; - t->flags |= TYPE_IS_FLEXIBLE | TYPE_IS_RESOLVED; + t->flags |= TYPE_IS_FLEXIBLE; break; case EXPR_LITERAL_STR: t->kind = TYPE_SLICE; @@ -835,22 +840,25 @@ static bool types_expr(Typer *tr, Expression *e) { t->slice->was_expr = NULL; t->slice->kind = TYPE_BUILTIN; t->slice->builtin = BUILTIN_CHAR; - t->flags |= TYPE_IS_RESOLVED; break; case EXPR_LITERAL_FLOAT: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_F32; - t->flags |= TYPE_IS_FLEXIBLE | TYPE_IS_RESOLVED; + t->flags |= TYPE_IS_FLEXIBLE; break; case EXPR_LITERAL_BOOL: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_BOOL; - t->flags |= TYPE_IS_RESOLVED; break; case EXPR_LITERAL_CHAR: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_CHAR; - t->flags |= TYPE_IS_RESOLVED; + break; + case EXPR_PKG: + t->kind = TYPE_PKG; + Expression *name_expr = e->pkg.name_expr; + if (!types_expr(tr, name_expr)) return false; + Value name_val; break; case EXPR_EACH: { EachExpr *ea = e->each; @@ -1476,10 +1484,9 @@ static bool types_expr(Typer *tr, Expression *e) { Expression *code = e->c.code; if (!types_expr(tr, code)) return false; - if (code->type.kind != TYPE_SLICE - || !type_is_builtin(code->type.slice, BUILTIN_CHAR)) { + if (!type_is_slicechar(&code->type)) { char *s = type_to_str(&code->type); - err_print(e->where, "Argument to #C directive must be a string, but got type %s."); + err_print(e->where, "Argument to #C directive must of type []char, but got type %s."); free(s); return false; } @@ -1732,8 +1739,7 @@ static bool types_expr(Typer *tr, Expression *e) { /* fallthrough */ case TYPE_STRUCT: { /* allow accessing struct members with a string */ - if (rhs_type->kind != TYPE_SLICE - || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) { + if (!type_is_slicechar(rhs_type)) { char *s = type_to_str(rhs_type); err_print(e->where, "Expected a string for struct member access with [], but got type %s.", s); return false; @@ -1803,10 +1809,11 @@ static bool types_expr(Typer *tr, Expression *e) { Value field_name; if (!types_expr(tr, rhs)) return false; - if (rhs_type->kind != TYPE_SLICE || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) { - err_print(e->where, "Invalid field of type %s."); + if (!type_is_slicechar(rhs_type)) { + char *s = type_to_str(rhs_type); + err_print(e->where, "Invalid field of type %s.", s); + free(s); return false; - } if (!eval_expr(tr->evalr, rhs, &field_name)) return false; char *str = field_name.slice.data; @@ -2125,7 +2132,7 @@ static bool types_file(Typer *tr, ParsedFile *f, char *code) { Value pkg_name; if (!types_expr(tr, f->pkg_name)) return false; - if (f->pkg_name->type.kind != TYPE_SLICE || !type_is_builtin(f->pkg_name->type.slice, BUILTIN_CHAR)) { + if (!type_is_slicechar(&f->pkg_name->type)) { char *typestr = type_to_str(&f->pkg_name->type); err_print(f->pkg_name->where, "Package names must be of type []char, but this is of type %s.", typestr); free(typestr); @@ -150,6 +150,7 @@ typedef union Value { union Value *tuple; Slice slice; struct Type *type; + struct Package *pkg; } Value; enum { @@ -187,6 +188,7 @@ typedef struct IdentTree { unsigned char index_in_parent; /* index of this in .parent.children */ bool export_name; /* is this identifier's name important? */ U64 export_id; /* 0 if there's no exported identifier here, otherwise unique positive integer associated with this identifier */ + struct Package *pkg; /* NULL if this is not associated with a package */ struct IdentTree *parent; struct IdentTree *children[TREE_NCHILDREN]; IdentDecl *decls; /* array of declarations of this identifier */ @@ -643,8 +645,9 @@ typedef struct Expression { struct { Type type; } del; - struct { - struct Expression *name; + union { + struct Expression *name_expr; + Identifier name_ident; } pkg; IfExpr if_; WhileExpr while_; @@ -763,6 +766,10 @@ typedef struct Typer { char *pkg_name; } Typer; +typedef struct Package { + Identifier name; + Identifiers idents; +} Package; typedef struct Exporter { FILE *out; /* .top (toc package) to output to */ @@ -790,6 +797,7 @@ typedef struct CGenerator { Identifiers *idents; } CGenerator; + #ifdef TOC_DEBUG #define add_ident_decls(b, d, flags) add_ident_decls_(__FILE__, __LINE__, b, d, flags) #endif |