diff options
| -rw-r--r-- | src/ast_render.cpp | 80 | ||||
| -rw-r--r-- | src/parseh.cpp | 29 | ||||
| -rw-r--r-- | test/run_tests.cpp | 45 |
3 files changed, 111 insertions, 43 deletions
diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 6fc8c31fb4..acec9d05c4 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -892,7 +892,7 @@ void ast_render(FILE *f, AstNode *node, int indent_size) { render_node_grouped(&ar, node); } -static void ast_render_tld_fn(AstRender *ar, TldFn *tld_fn) { +static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) { FnTableEntry *fn_entry = tld_fn->fn_entry; FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id; const char *visib_mod_str = visib_mod_string(tld_fn->base.visib_mod); @@ -917,15 +917,16 @@ static void ast_render_tld_fn(AstRender *ar, TldFn *tld_fn) { } } -static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { +static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) { VariableTableEntry *var = tld_var->var; const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); const char *const_or_var = const_or_var_string(var->src_is_const); const char *extern_str = extern_string(var->is_extern); - fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(&var->name)); + fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name)); if (var->value.type->id == TypeTableEntryIdNumLitFloat || - var->value.type->id == TypeTableEntryIdNumLitInt) + var->value.type->id == TypeTableEntryIdNumLitInt || + var->value.type->id == TypeTableEntryIdMetaType) { // skip type } else { @@ -937,11 +938,60 @@ static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { return; } - Buf buf = BUF_INIT; - buf_resize(&buf, 0); - render_const_value(&buf, &var->value); + fprintf(ar->f, " = "); - fprintf(ar->f, " = %s;\n", buf_ptr(&buf)); + if (var->value.special == ConstValSpecialStatic && + var->value.type->id == TypeTableEntryIdMetaType) + { + TypeTableEntry *type_entry = var->value.data.x_type; + if (type_entry->id == TypeTableEntryIdStruct) { + const char *extern_str = extern_string(type_entry->data.structure.is_extern); + fprintf(ar->f, "%sstruct {\n", extern_str); + for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { + TypeStructField *field = &type_entry->data.structure.fields[i]; + fprintf(ar->f, " "); + print_symbol(ar, field->name); + fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); + } + fprintf(ar->f, "}"); + } else if (type_entry->id == TypeTableEntryIdEnum) { + const char *extern_str = extern_string(type_entry->data.enumeration.is_extern); + fprintf(ar->f, "%senum {\n", extern_str); + for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) { + TypeEnumField *field = &type_entry->data.enumeration.fields[i]; + fprintf(ar->f, " "); + print_symbol(ar, field->name); + if (field->type_entry->id == TypeTableEntryIdVoid) { + fprintf(ar->f, ",\n"); + } else { + fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); + } + } + fprintf(ar->f, "}"); + } else if (type_entry->id == TypeTableEntryIdUnion) { + fprintf(ar->f, "union {"); + fprintf(ar->f, "TODO"); + fprintf(ar->f, "}"); + } else { + fprintf(ar->f, "%s", buf_ptr(&type_entry->name)); + } + } else { + Buf buf = BUF_INIT; + buf_resize(&buf, 0); + render_const_value(&buf, &var->value); + fprintf(ar->f, "%s", buf_ptr(&buf)); + } + + fprintf(ar->f, ";\n"); +} + +static void ast_render_tld_typedef(AstRender *ar, Buf *name, TldTypeDef *tld_typedef) { + TypeTableEntry *type_entry = tld_typedef->type_entry; + TypeTableEntry *canon_type = get_underlying_type(type_entry); + + fprintf(ar->f, "pub type "); + print_symbol(ar, name); + fprintf(ar->f, " = %s;\n", buf_ptr(&canon_type->name)); } void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { @@ -957,18 +1007,26 @@ void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { break; Tld *tld = entry->value; + + if (!buf_eql_buf(entry->key, tld->name)) { + fprintf(ar.f, "pub const "); + print_symbol(&ar, entry->key); + fprintf(ar.f, " = %s;\n", buf_ptr(tld->name)); + continue; + } + switch (tld->id) { case TldIdVar: - ast_render_tld_var(&ar, (TldVar *)tld); + ast_render_tld_var(&ar, entry->key, (TldVar *)tld); break; case TldIdFn: - ast_render_tld_fn(&ar, (TldFn *)tld); + ast_render_tld_fn(&ar, entry->key, (TldFn *)tld); break; case TldIdContainer: fprintf(stdout, "container\n"); break; case TldIdTypeDef: - fprintf(stdout, "typedef\n"); + ast_render_tld_typedef(&ar, entry->key, (TldTypeDef *)tld); break; } } diff --git a/src/parseh.cpp b/src/parseh.cpp index ff2f9c129a..b4ad039020 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -110,8 +110,17 @@ static void add_global(Context *c, Tld *tld) { } static Tld *get_global(Context *c, Buf *name) { - auto entry = c->import->decls_scope->decl_table.maybe_get(name); - return entry ? entry->value : nullptr; + { + auto entry = c->import->decls_scope->decl_table.maybe_get(name); + if (entry) + return entry->value; + } + { + auto entry = c->macro_table.maybe_get(name); + if (entry) + return entry->value; + } + return nullptr; } static const char *decl_name(const Decl *decl) { @@ -125,18 +134,18 @@ static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { } static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) { + auto entry = c->import->decls_scope->decl_table.maybe_get(name); + if (entry) { + Tld *existing_tld = entry->value; + assert(existing_tld->id == TldIdVar); + return (TldVar *)existing_tld; + } TldVar *tld_var = allocate<TldVar>(1); parseh_init_tld(c, &tld_var->base, TldIdVar, name); tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value); return tld_var; } -static Tld *create_global_char_lit_var(Context *c, Buf *name, uint8_t value) { - ConstExprValue *var_val = create_const_unsigned_negative(c->codegen->builtin_types.entry_u8, value, false); - TldVar *tld_var = create_global_var(c, name, var_val, true); - return &tld_var->base; -} - static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { TldVar *tld_var = create_global_var(c, name, create_const_str_lit(c->codegen, value), true); return &tld_var->base; @@ -1156,7 +1165,7 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch switch (tok->id) { case CTokIdCharLit: if (is_last && is_first) { - Tld *tld = create_global_char_lit_var(c, name, tok->data.char_lit); + Tld *tld = create_global_num_lit_unsigned_negative(c, name, tok->data.char_lit, false); c->macro_table.put(name, tld); } return; @@ -1228,7 +1237,7 @@ static void process_symbol_macros(Context *c) { } } - add_global_alias(c, ms.value, existing_tld); + add_global_alias(c, ms.name, existing_tld); } } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 395f9ab85c..cc61a2a684 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1754,13 +1754,14 @@ enum Foo { FooB, Foo1, }; - )SOURCE", 3, R"(export enum enum_Foo { + )SOURCE", 5, R"(pub const enum_Foo = extern enum { A, B, @"1", -})", R"(pub const FooA = enum_Foo.A; -pub const FooB = enum_Foo.B; -pub const Foo1 = enum_Foo.@"1";)", +};)", + R"(pub const FooA = 0;)", + R"(pub const FooB = 1;)", + R"(pub const Foo1 = 2;)", R"(pub const Foo = enum_Foo;)"); add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( @@ -1773,10 +1774,10 @@ struct Foo { char *y; }; )SOURCE", 2, - R"OUTPUT(export struct struct_Foo { + R"OUTPUT(const struct_Foo = extern struct { x: c_int, y: ?&u8, -})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); +};)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( struct Foo { @@ -1788,18 +1789,18 @@ enum Bar { BarB, }; void func(struct Foo *a, enum Bar **b); - )SOURCE", 5, R"OUTPUT(export struct struct_Foo { + )SOURCE", 7, R"OUTPUT(pub const struct_Foo = extern struct { x: c_int, y: c_int, -})OUTPUT", R"OUTPUT( -export enum enum_Bar { +};)OUTPUT", R"OUTPUT(pub const enum_Bar = extern enum { A, B, -})OUTPUT", R"OUTPUT(pub const BarA = enum_Bar.A; -pub const BarB = enum_Bar.B;)OUTPUT", +};)OUTPUT", + R"OUTPUT(pub const BarA = 0;)OUTPUT", + R"OUTPUT(pub const BarB = 1;)OUTPUT", "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", - R"OUTPUT(pub const Foo = struct_Foo; -pub const Bar = enum_Bar;)OUTPUT"); + R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT", + R"OUTPUT(pub const Bar = enum_Bar;)OUTPUT"); add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( void func(int array[20]); @@ -1811,22 +1812,22 @@ void func(int array[20]); struct Foo { void (*derp)(struct Foo *foo); }; - )SOURCE", 2, R"OUTPUT(export struct struct_Foo { + )SOURCE", 2, R"OUTPUT(pub const struct_Foo = extern struct { derp: ?extern fn(?&struct_Foo), -})OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); +};)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( struct Foo; struct Foo *some_func(struct Foo *foo, int x); - )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; -pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", + )SOURCE", 3, R"OUTPUT(pub type struct_Foo = u8;)OUTPUT", + R"OUTPUT(pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( #define A_CHAR 'a' - )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); + )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 97;)OUTPUT"); add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, @@ -1863,12 +1864,12 @@ struct Bar { struct Foo *next; }; )SOURCE", 2, - R"SOURCE(export struct struct_Bar { + R"SOURCE(pub const struct_Bar = extern struct { next: ?&struct_Foo, -})SOURCE", - R"SOURCE(export struct struct_Foo { +};)SOURCE", + R"SOURCE(pub const struct_Foo = extern struct { next: ?&struct_Bar, -})SOURCE"); +};)SOURCE"); add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( |
