| 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,7 +892,7 @@ void ast_render(FILE *f, AstNode *node, int indent_size) { |
| 892 | render_node_grouped(&ar, node); | 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 | FnTableEntry *fn_entry = tld_fn->fn_entry; | 896 | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 897 | FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id; | 897 | FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id; |
| 898 | const char *visib_mod_str = visib_mod_string(tld_fn->base.visib_mod); | 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,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 | VariableTableEntry *var = tld_var->var; | 921 | VariableTableEntry *var = tld_var->var; |
| 922 | const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); | 922 | const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); |
| 923 | const char *const_or_var = const_or_var_string(var->src_is_const); | 923 | const char *const_or_var = const_or_var_string(var->src_is_const); |
| 924 | const char *extern_str = extern_string(var->is_extern); | 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 | if (var->value.type->id == TypeTableEntryIdNumLitFloat || | 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 | // skip type | 931 | // skip type |
| 931 | } else { | 932 | } else { |
| ... | @@ -937,11 +938,60 @@ static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { | ... | @@ -937,11 +938,60 @@ static void ast_render_tld_var(AstRender *ar, TldVar *tld_var) { |
| 937 | return; | 938 | return; |
| 938 | } | 939 | } |
| 939 | 940 | ||
| 940 | Buf buf = BUF_INIT; | 941 | fprintf(ar->f, " = "); |
| 941 | buf_resize(&buf, 0); | ||
| 942 | render_const_value(&buf, &var->value); | ||
| 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 | void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { | 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,18 +1007,26 @@ void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { |
| 957 | break; | 1007 | break; |
| 958 | 1008 | ||
| 959 | Tld *tld = entry->value; | 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 | switch (tld->id) { | 1018 | switch (tld->id) { |
| 961 | case TldIdVar: | 1019 | case TldIdVar: |
| 962 | ast_render_tld_var(&ar, (TldVar *)tld); | 1020 | ast_render_tld_var(&ar, entry->key, (TldVar *)tld); |
| 963 | break; | 1021 | break; |
| 964 | case TldIdFn: | 1022 | case TldIdFn: |
| 965 | ast_render_tld_fn(&ar, (TldFn *)tld); | 1023 | ast_render_tld_fn(&ar, entry->key, (TldFn *)tld); |
| 966 | break; | 1024 | break; |
| 967 | case TldIdContainer: | 1025 | case TldIdContainer: |
| 968 | fprintf(stdout, "container\n"); | 1026 | fprintf(stdout, "container\n"); |
| 969 | break; | 1027 | break; |
| 970 | case TldIdTypeDef: | 1028 | case TldIdTypeDef: |
| 971 | fprintf(stdout, "typedef\n"); | 1029 | ast_render_tld_typedef(&ar, entry->key, (TldTypeDef *)tld); |
| 972 | break; | 1030 | break; |
| 973 | } | 1031 | } |
| 974 | } | 1032 | } |
src/parseh.cpp+19-10| ... | @@ -110,8 +110,17 @@ static void add_global(Context *c, Tld *tld) { | ... | @@ -110,8 +110,17 @@ static void add_global(Context *c, Tld *tld) { |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static Tld *get_global(Context *c, Buf *name) { | 112 | static Tld *get_global(Context *c, Buf *name) { |
| 113 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); | 113 | { |
| 114 | return entry ? entry->value : nullptr; | 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 | static const char *decl_name(const Decl *decl) { | 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,18 +134,18 @@ static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { |
| 125 | } | 134 | } |
| 126 | 135 | ||
| 127 | static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) { | 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 | TldVar *tld_var = allocate<TldVar>(1); | 143 | TldVar *tld_var = allocate<TldVar>(1); |
| 129 | parseh_init_tld(c, &tld_var->base, TldIdVar, name); | 144 | parseh_init_tld(c, &tld_var->base, TldIdVar, name); |
| 130 | tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value); | 145 | tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value); |
| 131 | return tld_var; | 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 | static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { | 149 | static Tld *create_global_str_lit_var(Context *c, Buf *name, Buf *value) { |
| 141 | TldVar *tld_var = create_global_var(c, name, create_const_str_lit(c->codegen, value), true); | 150 | TldVar *tld_var = create_global_var(c, name, create_const_str_lit(c->codegen, value), true); |
| 142 | return &tld_var->base; | 151 | return &tld_var->base; |
| ... | @@ -1156,7 +1165,7 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch | ... | @@ -1156,7 +1165,7 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch |
| 1156 | switch (tok->id) { | 1165 | switch (tok->id) { |
| 1157 | case CTokIdCharLit: | 1166 | case CTokIdCharLit: |
| 1158 | if (is_last && is_first) { | 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 | c->macro_table.put(name, tld); | 1169 | c->macro_table.put(name, tld); |
| 1161 | } | 1170 | } |
| 1162 | return; | 1171 | return; |
| ... | @@ -1228,7 +1237,7 @@ static void process_symbol_macros(Context *c) { | ... | @@ -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,13 +1754,14 @@ enum Foo { |
| 1754 | FooB, | 1754 | FooB, |
| 1755 | Foo1, | 1755 | Foo1, |
| 1756 | }; | 1756 | }; |
| 1757 | )SOURCE", 3, R"(export enum enum_Foo { | 1757 | )SOURCE", 5, R"(pub const enum_Foo = extern enum { |
| 1758 | A, | 1758 | A, |
| 1759 | B, | 1759 | B, |
| 1760 | @"1", | 1760 | @"1", |
| 1761 | })", R"(pub const FooA = enum_Foo.A; | 1761 | };)", |
| 1762 | pub const FooB = enum_Foo.B; | 1762 | R"(pub const FooA = 0;)", |
| 1763 | pub const Foo1 = enum_Foo.@"1";)", | 1763 | R"(pub const FooB = 1;)", |
| 1764 | R"(pub const Foo1 = 2;)", | ||
| 1764 | R"(pub const Foo = enum_Foo;)"); | 1765 | R"(pub const Foo = enum_Foo;)"); |
| 1765 | 1766 | ||
| 1766 | add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( | 1767 | add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( |
| ... | @@ -1773,10 +1774,10 @@ struct Foo { | ... | @@ -1773,10 +1774,10 @@ struct Foo { |
| 1773 | char *y; | 1774 | char *y; |
| 1774 | }; | 1775 | }; |
| 1775 | )SOURCE", 2, | 1776 | )SOURCE", 2, |
| 1776 | R"OUTPUT(export struct struct_Foo { | 1777 | R"OUTPUT(const struct_Foo = extern struct { |
| 1777 | x: c_int, | 1778 | x: c_int, |
| 1778 | y: ?&u8, | 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 | add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( | 1782 | add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( |
| 1782 | struct Foo { | 1783 | struct Foo { |
| ... | @@ -1788,18 +1789,18 @@ enum Bar { | ... | @@ -1788,18 +1789,18 @@ enum Bar { |
| 1788 | BarB, | 1789 | BarB, |
| 1789 | }; | 1790 | }; |
| 1790 | void func(struct Foo *a, enum Bar **b); | 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 | x: c_int, | 1793 | x: c_int, |
| 1793 | y: c_int, | 1794 | y: c_int, |
| 1794 | })OUTPUT", R"OUTPUT( | 1795 | };)OUTPUT", R"OUTPUT(pub const enum_Bar = extern enum { |
| 1795 | export enum enum_Bar { | ||
| 1796 | A, | 1796 | A, |
| 1797 | B, | 1797 | B, |
| 1798 | })OUTPUT", R"OUTPUT(pub const BarA = enum_Bar.A; | 1798 | };)OUTPUT", |
| 1799 | pub const BarB = enum_Bar.B;)OUTPUT", | 1799 | R"OUTPUT(pub const BarA = 0;)OUTPUT", |
| 1800 | R"OUTPUT(pub const BarB = 1;)OUTPUT", | ||
| 1800 | "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", | 1801 | "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", |
| 1801 | R"OUTPUT(pub const Foo = struct_Foo; | 1802 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT", |
| 1802 | pub const Bar = enum_Bar;)OUTPUT"); | 1803 | R"OUTPUT(pub const Bar = enum_Bar;)OUTPUT"); |
| 1803 | 1804 | ||
| 1804 | add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( | 1805 | add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( |
| 1805 | void func(int array[20]); | 1806 | void func(int array[20]); |
| ... | @@ -1811,22 +1812,22 @@ void func(int array[20]); | ... | @@ -1811,22 +1812,22 @@ void func(int array[20]); |
| 1811 | struct Foo { | 1812 | struct Foo { |
| 1812 | void (*derp)(struct Foo *foo); | 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 | derp: ?extern fn(?&struct_Foo), | 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 | add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( | 1820 | add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( |
| 1820 | struct Foo; | 1821 | struct Foo; |
| 1821 | struct Foo *some_func(struct Foo *foo, int x); | 1822 | struct Foo *some_func(struct Foo *foo, int x); |
| 1822 | )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; | 1823 | )SOURCE", 3, R"OUTPUT(pub type struct_Foo = u8;)OUTPUT", |
| 1823 | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", | 1824 | R"OUTPUT(pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1824 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | 1825 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1825 | 1826 | ||
| 1826 | 1827 | ||
| 1827 | add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( | 1828 | add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( |
| 1828 | #define A_CHAR 'a' | 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 | add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, | 1833 | add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, |
| ... | @@ -1863,12 +1864,12 @@ struct Bar { | ... | @@ -1863,12 +1864,12 @@ struct Bar { |
| 1863 | struct Foo *next; | 1864 | struct Foo *next; |
| 1864 | }; | 1865 | }; |
| 1865 | )SOURCE", 2, | 1866 | )SOURCE", 2, |
| 1866 | R"SOURCE(export struct struct_Bar { | 1867 | R"SOURCE(pub const struct_Bar = extern struct { |
| 1867 | next: ?&struct_Foo, | 1868 | next: ?&struct_Foo, |
| 1868 | })SOURCE", | 1869 | };)SOURCE", |
| 1869 | R"SOURCE(export struct struct_Foo { | 1870 | R"SOURCE(pub const struct_Foo = extern struct { |
| 1870 | next: ?&struct_Bar, | 1871 | next: ?&struct_Bar, |
| 1871 | })SOURCE"); | 1872 | };)SOURCE"); |
| 1872 | 1873 | ||
| 1873 | 1874 | ||
| 1874 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( | 1875 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( |