authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 02:17:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 02:17:51-07:00
loga94ad9e89c8e9f1ca11ca194f690460725676b3b
tree82459f85308b8fc50790b35ad2a5bcd6a1ff2388
parentc1691afdd90b744200f2238afe52d7fd9e6471b6

parseh defines can reference other defines


4 files changed, 95 insertions(+), 18 deletions(-)

src/parseh.cpp+69-18
...@@ -20,6 +20,11 @@...@@ -20,6 +20,11 @@
2020
21using namespace clang;21using namespace clang;
2222
23struct MacroSymbol {
24 Buf *name;
25 Buf *value;
26};
27
23struct Context {28struct Context {
24 ImportTableEntry *import;29 ImportTableEntry *import;
25 ZigList<ErrorMsg *> *errors;30 ZigList<ErrorMsg *> *errors;
...@@ -27,13 +32,14 @@ struct Context {...@@ -27,13 +32,14 @@ struct Context {
27 VisibMod visib_mod;32 VisibMod visib_mod;
28 bool have_c_void_decl_node;33 bool have_c_void_decl_node;
29 AstNode *root;34 AstNode *root;
30 HashMap<Buf *, bool, buf_hash, buf_eql_buf> root_type_table;35 HashMap<Buf *, bool, buf_hash, buf_eql_buf> root_name_table;
31 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;36 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;
32 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;37 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;
33 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;38 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
34 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;39 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
35 SourceManager *source_manager;40 SourceManager *source_manager;
36 ZigList<AstNode *> aliases;41 ZigList<AstNode *> aliases;
42 ZigList<MacroSymbol> macro_symbols;
37};43};
3844
39static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl);45static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl);
...@@ -169,7 +175,7 @@ static AstNode *add_typedef_node(Context *c, Buf *new_name, AstNode *target_node...@@ -169,7 +175,7 @@ static AstNode *add_typedef_node(Context *c, Buf *new_name, AstNode *target_node
169 }175 }
170 AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node);176 AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node);
171177
172 c->root_type_table.put(new_name, true);178 c->root_name_table.put(new_name, true);
173 c->root->data.root.top_level_decls.append(node);179 c->root->data.root.top_level_decls.append(node);
174 return node;180 return node;
175}181}
...@@ -453,7 +459,7 @@ static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const De...@@ -453,7 +459,7 @@ static AstNode *make_qual_type_node_with_table(Context *c, QualType qt, const De
453}459}
454460
455static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) {461static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) {
456 return make_qual_type_node_with_table(c, qt, decl, &c->root_type_table);462 return make_qual_type_node_with_table(c, qt, decl, &c->root_name_table);
457}463}
458464
459static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {465static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
...@@ -576,13 +582,12 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -576,13 +582,12 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
576 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));582 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(bare_name));
577 return;583 return;
578 }584 }
579 Buf enum_val_name = BUF_INIT;585 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
580 buf_init_from_str(&enum_val_name, decl_name(enum_const));
581586
582 Buf field_name = BUF_INIT;587 Buf field_name = BUF_INIT;
583588
584 if (buf_starts_with_buf(&enum_val_name, bare_name)) {589 if (buf_starts_with_buf(enum_val_name, bare_name)) {
585 Buf *slice = buf_slice(&enum_val_name, buf_len(bare_name), buf_len(&enum_val_name));590 Buf *slice = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
586 if (valid_symbol_starter(buf_ptr(slice)[0])) {591 if (valid_symbol_starter(buf_ptr(slice)[0])) {
587 buf_init_from_buf(&field_name, slice);592 buf_init_from_buf(&field_name, slice);
588 } else {593 } else {
...@@ -590,7 +595,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -590,7 +595,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
590 buf_appendf(&field_name, "_%s", buf_ptr(slice));595 buf_appendf(&field_name, "_%s", buf_ptr(slice));
591 }596 }
592 } else {597 } else {
593 buf_init_from_buf(&field_name, &enum_val_name);598 buf_init_from_buf(&field_name, enum_val_name);
594 }599 }
595600
596 AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void"));601 AstNode *field_node = create_struct_field_node(c, buf_ptr(&field_name), create_symbol_node(c, "void"));
...@@ -598,8 +603,9 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -598,8 +603,9 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
598603
599 // in C each enum value is in the global namespace. so we put them there too.604 // in C each enum value is in the global namespace. so we put them there too.
600 AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(&field_name));605 AstNode *field_access_node = create_field_access_node(c, buf_ptr(full_type_name), buf_ptr(&field_name));
601 AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node);606 AstNode *var_node = create_var_decl_node(c, buf_ptr(enum_val_name), field_access_node);
602 var_decls.append(var_node);607 var_decls.append(var_node);
608 c->root_name_table.put(enum_val_name, true);
603 }609 }
604610
605 normalize_parent_ptrs(node);611 normalize_parent_ptrs(node);
...@@ -704,18 +710,25 @@ static bool decl_visitor(void *context, const Decl *decl) {...@@ -704,18 +710,25 @@ static bool decl_visitor(void *context, const Decl *decl) {
704 return true;710 return true;
705}711}
706712
713static bool name_exists(Context *c, Buf *name) {
714 if (c->root_name_table.maybe_get(name)) {
715 return true;
716 }
717 if (c->fn_table.maybe_get(name)) {
718 return true;
719 }
720 if (c->macro_table.maybe_get(name)) {
721 return true;
722 }
723 return false;
724}
725
707static void render_aliases(Context *c) {726static void render_aliases(Context *c) {
708 for (int i = 0; i < c->aliases.length; i += 1) {727 for (int i = 0; i < c->aliases.length; i += 1) {
709 AstNode *alias_node = c->aliases.at(i);728 AstNode *alias_node = c->aliases.at(i);
710 assert(alias_node->type == NodeTypeVariableDeclaration);729 assert(alias_node->type == NodeTypeVariableDeclaration);
711 Buf *name = &alias_node->data.variable_declaration.symbol;730 Buf *name = &alias_node->data.variable_declaration.symbol;
712 if (c->root_type_table.maybe_get(name)) {731 if (name_exists(c, name)) {
713 continue;
714 }
715 if (c->fn_table.maybe_get(name)) {
716 continue;
717 }
718 if (c->macro_table.maybe_get(name)) {
719 continue;732 continue;
720 }733 }
721 c->root->data.root.top_level_decls.append(alias_node);734 c->root->data.root.top_level_decls.append(alias_node);
...@@ -791,7 +804,30 @@ static int parse_c_num_lit_unsigned(Buf *buf, uint64_t *out_val) {...@@ -791,7 +804,30 @@ static int parse_c_num_lit_unsigned(Buf *buf, uint64_t *out_val) {
791 return 0;804 return 0;
792}805}
793806
807static bool is_simple_symbol(Buf *buf) {
808 bool first = true;
809 for (int i = 0; i < buf_len(buf); i += 1) {
810 uint8_t c = buf_ptr(buf)[i];
811 bool valid_alpha = (c >= 'a' && c <= 'z') ||
812 (c >= 'A' && c <= 'Z') || c == '_';
813 bool valid_digit = (c >= '0' && c <= '9');
814
815 bool ok = (valid_alpha || (!first && valid_digit));
816 first = false;
817
818 if (!ok) {
819 return false;
820 }
821 }
822 return true;
823}
824
794static void process_macro(Context *c, Buf *name, Buf *value) {825static void process_macro(Context *c, Buf *name, Buf *value) {
826 //fprintf(stderr, "macro '%s' = '%s'\n", buf_ptr(name), buf_ptr(value));
827 if (is_zig_keyword(name)) {
828 return;
829 }
830
795 // maybe it's a character literal831 // maybe it's a character literal
796 uint8_t ch;832 uint8_t ch;
797 if (!parse_c_char_lit(value, &ch)) {833 if (!parse_c_char_lit(value, &ch)) {
...@@ -811,7 +847,20 @@ static void process_macro(Context *c, Buf *name, Buf *value) {...@@ -811,7 +847,20 @@ static void process_macro(Context *c, Buf *name, Buf *value) {
811 }847 }
812848
813 // maybe it's a symbol849 // maybe it's a symbol
814 // TODO850 if (is_simple_symbol(value)) {
851 c->macro_symbols.append({name, value});
852 }
853}
854
855static void process_symbol_macros(Context *c) {
856 for (int i = 0; i < c->macro_symbols.length; i += 1) {
857 MacroSymbol ms = c->macro_symbols.at(i);
858 if (name_exists(c, ms.value)) {
859 AstNode *var_node = create_var_decl_node(c, buf_ptr(ms.name),
860 create_symbol_node(c, buf_ptr(ms.value)));
861 c->macro_table.put(ms.name, var_node);
862 }
863 }
815}864}
816865
817static void process_preprocessor_entities(Context *c, ASTUnit &unit) {866static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
...@@ -885,7 +934,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,...@@ -885,7 +934,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
885 c->import = import;934 c->import = import;
886 c->errors = errors;935 c->errors = errors;
887 c->visib_mod = VisibModPub;936 c->visib_mod = VisibModPub;
888 c->root_type_table.init(8);937 c->root_name_table.init(8);
889 c->enum_type_table.init(8);938 c->enum_type_table.init(8);
890 c->struct_type_table.init(8);939 c->struct_type_table.init(8);
891 c->fn_table.init(8);940 c->fn_table.init(8);
...@@ -991,6 +1040,8 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,...@@ -991,6 +1040,8 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
9911040
992 process_preprocessor_entities(c, *ast_unit);1041 process_preprocessor_entities(c, *ast_unit);
9931042
1043 process_symbol_macros(c);
1044
994 render_macros(c);1045 render_macros(c);
995 render_aliases(c);1046 render_aliases(c);
9961047
src/tokenizer.cpp+16
...@@ -97,6 +97,22 @@...@@ -97,6 +97,22 @@
97 ALPHA: \97 ALPHA: \
98 case '_'98 case '_'
9999
100const char * zig_keywords[] = {
101 "true", "false", "null", "fn", "return", "var", "const", "extern",
102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",
103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104 "null", "noalias", "switch", "undefined", "error"
105};
106
107bool is_zig_keyword(Buf *buf) {
108 for (int i = 0; i < array_length(zig_keywords); i += 1) {
109 if (buf_eql_str(buf, zig_keywords[i])) {
110 return true;
111 }
112 }
113 return false;
114}
115
100enum TokenizeState {116enum TokenizeState {
101 TokenizeStateStart,117 TokenizeStateStart,
102 TokenizeStateSymbol,118 TokenizeStateSymbol,
src/tokenizer.hpp+1
...@@ -131,5 +131,6 @@ int get_digit_value(uint8_t c);...@@ -131,5 +131,6 @@ int get_digit_value(uint8_t c);
131const char * token_name(TokenId id);131const char * token_name(TokenId id);
132132
133bool valid_symbol_starter(uint8_t c);133bool valid_symbol_starter(uint8_t c);
134bool is_zig_keyword(Buf *buf);
134135
135#endif136#endif
test/run_tests.cpp+9
...@@ -1998,10 +1998,19 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",...@@ -1998,10 +1998,19 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
1998#define CHANNEL_COUNT 241998#define CHANNEL_COUNT 24
1999 )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT");1999 )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT");
20002000
2001
2001 add_parseh_case("overide previous #define", R"SOURCE(2002 add_parseh_case("overide previous #define", R"SOURCE(
2002#define A_CHAR 'a'2003#define A_CHAR 'a'
2003#define A_CHAR 'b'2004#define A_CHAR 'b'
2004 )SOURCE", 1, "pub const A_CHAR = 'b';");2005 )SOURCE", 1, "pub const A_CHAR = 'b';");
2006
2007
2008 add_parseh_case("#define referencing another #define", R"SOURCE(
2009#define THING2 THING1
2010#define THING1 1234
2011 )SOURCE", 2,
2012 "pub const THING1 = 1234;",
2013 "pub const THING2 = THING1;");
2005}2014}
20062015
2007static void print_compiler_invocation(TestCase *test_case) {2016static void print_compiler_invocation(TestCase *test_case) {