| author | |
| committer | |
| log | 76b1cbc2ea50be928608b80bdd8ab25cd1b964f3 |
| tree | 502cc76e0517debc879feb5c05319a379bf3a84b |
| parent | 25a670d74e16463c7a8f91c3af91f44bf52a9e27 |
3 files changed, 111 insertions(+), 43 deletions(-)
src/ast_render.cpp+69-11| ... | ... | @@ -892,7 +892,7 @@ void ast_render(FILE *f, AstNode *node, int indent_size) { |
| 892 | 892 | render_node_grouped(&ar, node); |
| 893 | 893 | } |
| 894 | 894 | |
| 895 | static void ast_render_tld_fn(AstRender *ar, TldFn *tld_fn) { | |
| 895 | static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) { | |
| 896 | 896 | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 897 | 897 | FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id; |
| 898 | 898 | 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) { |
| 917 | 917 | } |
| 918 | 918 | } |
| 919 | 919 | |
| 920 | static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { | |
| 920 | static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) { | |
| 921 | 921 | VariableTableEntry *var = tld_var->var; |
| 922 | 922 | const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); |
| 923 | 923 | const char *const_or_var = const_or_var_string(var->src_is_const); |
| 924 | 924 | const char *extern_str = extern_string(var->is_extern); |
| 925 | fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(&var->name)); | |
| 925 | fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name)); | |
| 926 | 926 | |
| 927 | 927 | if (var->value.type->id == TypeTableEntryIdNumLitFloat || |
| 928 | var->value.type->id == TypeTableEntryIdNumLitInt) | |
| 928 | var->value.type->id == TypeTableEntryIdNumLitInt || | |
| 929 | var->value.type->id == TypeTableEntryIdMetaType) | |
| 929 | 930 | { |
| 930 | 931 | // skip type |
| 931 | 932 | } else { |
| ... | ... | @@ -937,11 +938,60 @@ static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { |
| 937 | 938 | return; |
| 938 | 939 | } |
| 939 | 940 | |
| 940 | Buf buf = BUF_INIT; | |
| 941 | buf_resize(&buf, 0); | |
| 942 | render_const_value(&buf, &var->value); | |
| 941 | fprintf(ar->f, " = "); | |
| 943 | 942 | |
| 944 | fprintf(ar->f, " = %s;\n", buf_ptr(&buf)); | |
| 943 | if (var->value.special == ConstValSpecialStatic && | |
| 944 | var->value.type->id == TypeTableEntryIdMetaType) | |
| 945 | { | |
| 946 | TypeTableEntry *type_entry = var->value.data.x_type; | |
| 947 | if (type_entry->id == TypeTableEntryIdStruct) { | |
| 948 | const char *extern_str = extern_string(type_entry->data.structure.is_extern); | |
| 949 | fprintf(ar->f, "%sstruct {\n", extern_str); | |
| 950 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 951 | TypeStructField *field = &type_entry->data.structure.fields[i]; | |
| 952 | fprintf(ar->f, " "); | |
| 953 | print_symbol(ar, field->name); | |
| 954 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 955 | } | |
| 956 | fprintf(ar->f, "}"); | |
| 957 | } else if (type_entry->id == TypeTableEntryIdEnum) { | |
| 958 | const char *extern_str = extern_string(type_entry->data.enumeration.is_extern); | |
| 959 | fprintf(ar->f, "%senum {\n", extern_str); | |
| 960 | for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) { | |
| 961 | TypeEnumField *field = &type_entry->data.enumeration.fields[i]; | |
| 962 | fprintf(ar->f, " "); | |
| 963 | print_symbol(ar, field->name); | |
| 964 | if (field->type_entry->id == TypeTableEntryIdVoid) { | |
| 965 | fprintf(ar->f, ",\n"); | |
| 966 | } else { | |
| 967 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 968 | } | |
| 969 | } | |
| 970 | fprintf(ar->f, "}"); | |
| 971 | } else if (type_entry->id == TypeTableEntryIdUnion) { | |
| 972 | fprintf(ar->f, "union {"); | |
| 973 | fprintf(ar->f, "TODO"); | |
| 974 | fprintf(ar->f, "}"); | |
| 975 | } else { | |
| 976 | fprintf(ar->f, "%s", buf_ptr(&type_entry->name)); | |
| 977 | } | |
| 978 | } else { | |
| 979 | Buf buf = BUF_INIT; | |
| 980 | buf_resize(&buf, 0); | |
| 981 | render_const_value(&buf, &var->value); | |
| 982 | fprintf(ar->f, "%s", buf_ptr(&buf)); | |
| 983 | } | |
| 984 | ||
| 985 | fprintf(ar->f, ";\n"); | |
| 986 | } | |
| 987 | ||
| 988 | static void ast_render_tld_typedef(AstRender *ar, Buf *name, TldTypeDef *tld_typedef) { | |
| 989 | TypeTableEntry *type_entry = tld_typedef->type_entry; | |
| 990 | TypeTableEntry *canon_type = get_underlying_type(type_entry); | |
| 991 | ||
| 992 | fprintf(ar->f, "pub type "); | |
| 993 | print_symbol(ar, name); | |
| 994 | fprintf(ar->f, " = %s;\n", buf_ptr(&canon_type->name)); | |
| 945 | 995 | } |
| 946 | 996 | |
| 947 | 997 | 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) { |
| 957 | 1007 | break; |
| 958 | 1008 | |
| 959 | 1009 | Tld *tld = entry->value; |
| 1010 | ||
| 1011 | if (!buf_eql_buf(entry->key, tld->name)) { | |
| 1012 | fprintf(ar.f, "pub const "); | |
| 1013 | print_symbol(&ar, entry->key); | |
| 1014 | fprintf(ar.f, " = %s;\n", buf_ptr(tld->name)); | |
| 1015 | continue; | |
| 1016 | } | |
| 1017 | ||
| 960 | 1018 | switch (tld->id) { |
| 961 | 1019 | case TldIdVar: |
| 962 | ast_render_tld_var(&ar, (TldVar *)tld); | |
| 1020 | ast_render_tld_var(&ar, entry->key, (TldVar *)tld); | |
| 963 | 1021 | break; |
| 964 | 1022 | case TldIdFn: |
| 965 | ast_render_tld_fn(&ar, (TldFn *)tld); | |
| 1023 | ast_render_tld_fn(&ar, entry->key, (TldFn *)tld); | |
| 966 | 1024 | break; |
| 967 | 1025 | case TldIdContainer: |
| 968 | 1026 | fprintf(stdout, "container\n"); |
| 969 | 1027 | break; |
| 970 | 1028 | case TldIdTypeDef: |
| 971 | fprintf(stdout, "typedef\n"); | |
| 1029 | ast_render_tld_typedef(&ar, entry->key, (TldTypeDef *)tld); | |
| 972 | 1030 | break; |
| 973 | 1031 | } |
| 974 | 1032 | } |
src/parseh.cpp+19-10| ... | ... | @@ -110,8 +110,17 @@ static void add_global(Context *c, Tld *tld) { |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | static Tld *get_global(Context *c, Buf *name) { |
| 113 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); | |
| 114 | return entry ? entry->value : nullptr; | |
| 113 | { | |
| 114 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); | |
| 115 | if (entry) | |
| 116 | return entry->value; | |
| 117 | } | |
| 118 | { | |
| 119 | auto entry = c->macro_table.maybe_get(name); | |
| 120 | if (entry) | |
| 121 | return entry->value; | |
| 122 | } | |
| 123 | return nullptr; | |
| 115 | 124 | } |
| 116 | 125 | |
| 117 | 126 | 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) { |
| 125 | 134 | } |
| 126 | 135 | |
| 127 | 136 | static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) { |
| 137 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); | |
| 138 | if (entry) { | |
| 139 | Tld *existing_tld = entry->value; | |
| 140 | assert(existing_tld->id == TldIdVar); | |
| 141 | return (TldVar *)existing_tld; | |
| 142 | } | |
| 128 | 143 | TldVar *tld_var = allocate<TldVar>(1); |
| 129 | 144 | parseh_init_tld(c, &tld_var->base, TldIdVar, name); |
| 130 | 145 | tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value); |
| 131 | 146 | return tld_var; |
| 132 | 147 | } |
| 133 | 148 | |
| 134 | static Tld *create_global_char_lit_var(Context *c, Buf *name, uint8_t value) { | |
| 135 | ConstExprValue *var_val = create_const_unsigned_negative(c->codegen->builtin_types.entry_u8, value, false); | |
| 136 | TldVar *tld_var = create_global_var(c, name, var_val, true); | |
| 137 | return &tld_var->base; | |
| 138 | } | |
| 139 | ||
| 140 | 149 | static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { |
| 141 | 150 | TldVar *tld_var = create_global_var(c, name, create_const_str_lit(c->codegen, value), true); |
| 142 | 151 | return &tld_var->base; |
| ... | ... | @@ -1156,7 +1165,7 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 1156 | 1165 | switch (tok->id) { |
| 1157 | 1166 | case CTokIdCharLit: |
| 1158 | 1167 | if (is_last && is_first) { |
| 1159 | Tld *tld = create_global_char_lit_var(c, name, tok->data.char_lit); | |
| 1168 | Tld *tld = create_global_num_lit_unsigned_negative(c, name, tok->data.char_lit, false); | |
| 1160 | 1169 | c->macro_table.put(name, tld); |
| 1161 | 1170 | } |
| 1162 | 1171 | return; |
| ... | ... | @@ -1228,7 +1237,7 @@ static void process_symbol_macros(Context *c) { |
| 1228 | 1237 | } |
| 1229 | 1238 | } |
| 1230 | 1239 | |
| 1231 | add_global_alias(c, ms.value, existing_tld); | |
| 1240 | add_global_alias(c, ms.name, existing_tld); | |
| 1232 | 1241 | } |
| 1233 | 1242 | } |
| 1234 | 1243 |
test/run_tests.cpp+23-22| ... | ... | @@ -1754,13 +1754,14 @@ enum Foo { |
| 1754 | 1754 | FooB, |
| 1755 | 1755 | Foo1, |
| 1756 | 1756 | }; |
| 1757 | )SOURCE", 3, R"(export enum enum_Foo { | |
| 1757 | )SOURCE", 5, R"(pub const enum_Foo = extern enum { | |
| 1758 | 1758 | A, |
| 1759 | 1759 | B, |
| 1760 | 1760 | @"1", |
| 1761 | })", R"(pub const FooA = enum_Foo.A; | |
| 1762 | pub const FooB = enum_Foo.B; | |
| 1763 | pub const Foo1 = enum_Foo.@"1";)", | |
| 1761 | };)", | |
| 1762 | R"(pub const FooA = 0;)", | |
| 1763 | R"(pub const FooB = 1;)", | |
| 1764 | R"(pub const Foo1 = 2;)", | |
| 1764 | 1765 | R"(pub const Foo = enum_Foo;)"); |
| 1765 | 1766 | |
| 1766 | 1767 | add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( |
| ... | ... | @@ -1773,10 +1774,10 @@ struct Foo { |
| 1773 | 1774 | char *y; |
| 1774 | 1775 | }; |
| 1775 | 1776 | )SOURCE", 2, |
| 1776 | R"OUTPUT(export struct struct_Foo { | |
| 1777 | R"OUTPUT(const struct_Foo = extern struct { | |
| 1777 | 1778 | x: c_int, |
| 1778 | 1779 | y: ?&u8, |
| 1779 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | |
| 1780 | };)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | |
| 1780 | 1781 | |
| 1781 | 1782 | add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( |
| 1782 | 1783 | struct Foo { |
| ... | ... | @@ -1788,18 +1789,18 @@ enum Bar { |
| 1788 | 1789 | BarB, |
| 1789 | 1790 | }; |
| 1790 | 1791 | void func(struct Foo *a, enum Bar **b); |
| 1791 | )SOURCE", 5, R"OUTPUT(export struct struct_Foo { | |
| 1792 | )SOURCE", 7, R"OUTPUT(pub const struct_Foo = extern struct { | |
| 1792 | 1793 | x: c_int, |
| 1793 | 1794 | y: c_int, |
| 1794 | })OUTPUT", R"OUTPUT( | |
| 1795 | export enum enum_Bar { | |
| 1795 | };)OUTPUT", R"OUTPUT(pub const enum_Bar = extern enum { | |
| 1796 | 1796 | A, |
| 1797 | 1797 | B, |
| 1798 | })OUTPUT", R"OUTPUT(pub const BarA = enum_Bar.A; | |
| 1799 | pub const BarB = enum_Bar.B;)OUTPUT", | |
| 1798 | };)OUTPUT", | |
| 1799 | R"OUTPUT(pub const BarA = 0;)OUTPUT", | |
| 1800 | R"OUTPUT(pub const BarB = 1;)OUTPUT", | |
| 1800 | 1801 | "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", |
| 1801 | R"OUTPUT(pub const Foo = struct_Foo; | |
| 1802 | pub const Bar = enum_Bar;)OUTPUT"); | |
| 1802 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT", | |
| 1803 | R"OUTPUT(pub const Bar = enum_Bar;)OUTPUT"); | |
| 1803 | 1804 | |
| 1804 | 1805 | add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( |
| 1805 | 1806 | void func(int array[20]); |
| ... | ... | @@ -1811,22 +1812,22 @@ void func(int array[20]); |
| 1811 | 1812 | struct Foo { |
| 1812 | 1813 | void (*derp)(struct Foo *foo); |
| 1813 | 1814 | }; |
| 1814 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { | |
| 1815 | )SOURCE", 2, R"OUTPUT(pub const struct_Foo = extern struct { | |
| 1815 | 1816 | derp: ?extern fn(?&struct_Foo), |
| 1816 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | |
| 1817 | };)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | |
| 1817 | 1818 | |
| 1818 | 1819 | |
| 1819 | 1820 | add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( |
| 1820 | 1821 | struct Foo; |
| 1821 | 1822 | struct Foo *some_func(struct Foo *foo, int x); |
| 1822 | )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; | |
| 1823 | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", | |
| 1823 | )SOURCE", 3, R"OUTPUT(pub type struct_Foo = u8;)OUTPUT", | |
| 1824 | R"OUTPUT(pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", | |
| 1824 | 1825 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1825 | 1826 | |
| 1826 | 1827 | |
| 1827 | 1828 | add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( |
| 1828 | 1829 | #define A_CHAR 'a' |
| 1829 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); | |
| 1830 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 97;)OUTPUT"); | |
| 1830 | 1831 | |
| 1831 | 1832 | |
| 1832 | 1833 | add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, |
| ... | ... | @@ -1863,12 +1864,12 @@ struct Bar { |
| 1863 | 1864 | struct Foo *next; |
| 1864 | 1865 | }; |
| 1865 | 1866 | )SOURCE", 2, |
| 1866 | R"SOURCE(export struct struct_Bar { | |
| 1867 | R"SOURCE(pub const struct_Bar = extern struct { | |
| 1867 | 1868 | next: ?&struct_Foo, |
| 1868 | })SOURCE", | |
| 1869 | R"SOURCE(export struct struct_Foo { | |
| 1869 | };)SOURCE", | |
| 1870 | R"SOURCE(pub const struct_Foo = extern struct { | |
| 1870 | 1871 | next: ?&struct_Bar, |
| 1871 | })SOURCE"); | |
| 1872 | };)SOURCE"); | |
| 1872 | 1873 | |
| 1873 | 1874 | |
| 1874 | 1875 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( |