authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 01:25:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 01:25:20-07:00
log35b74d4013a81066cd45f4c99ec20907db310340
treece756e0719a57bd6808a86a67cc876f54f7ab8f6
parent49d0971cd4f6aa3f897a0f36272c05c641e25f79

order-independent declarations even from imports

closes #42

3 files changed, 100 insertions(+), 92 deletions(-)

src/analyze.cpp+93-92
......@@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
807807 if (fn_def_node) {
808808 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
809809 }
810
811 if (is_pub && !struct_type) {
812 for (int i = 0; i < import->importers.length; i += 1) {
813 ImporterInfo importer = import->importers.at(i);
814 auto table_entry = importer.import->fn_table.maybe_get(proto_name);
815 if (table_entry) {
816 add_node_error(g, importer.source_node,
817 buf_sprintf("import of function '%s' overrides existing definition",
818 buf_ptr(proto_name)));
819 } else {
820 importer.import->fn_table.put(proto_name, fn_table_entry);
821 }
822 }
823 }
810824}
811825
812826static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
......@@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
17151729 variable_entry->is_ptr = true;
17161730 variable_entry->decl_node = source_node;
17171731 context->variable_table.put(&variable_entry->name, variable_entry);
1732
1733 bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);
1734 if (is_pub) {
1735 for (int i = 0; i < import->importers.length; i += 1) {
1736 ImporterInfo importer = import->importers.at(i);
1737 auto table_entry = importer.import->block_context->variable_table.maybe_get(&variable_entry->name);
1738 if (table_entry) {
1739 add_node_error(g, importer.source_node,
1740 buf_sprintf("import of variable '%s' overrides existing definition",
1741 buf_ptr(&variable_entry->name)));
1742 } else {
1743 importer.import->block_context->variable_table.put(&variable_entry->name, variable_entry);
1744 }
1745 }
1746 }
1747
1748
17181749 return variable_entry;
17191750 }
17201751 return nullptr;
......@@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
25632594 // already looked at these in the preview pass
25642595 break;
25652596 case NodeTypeUse:
2566 {
2567 for (int i = 0; i < node->data.use.directives->length; i += 1) {
2568 AstNode *directive_node = node->data.use.directives->at(i);
2569 Buf *name = &directive_node->data.directive.name;
2570 add_node_error(g, directive_node,
2571 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
2572 }
2573
2574 ImportTableEntry *target_import = node->codegen_node->data.import_node.import;
2575 assert(target_import);
2576
2577 // import all the public functions
2578 {
2579 auto it = target_import->fn_table.entry_iterator();
2580 for (;;) {
2581 auto *entry = it.next();
2582 if (!entry)
2583 break;
2584
2585 FnTableEntry *fn_entry = entry->value;
2586 bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != VisibModPrivate);
2587 if (is_pub) {
2588 auto existing_entry = import->fn_table.maybe_get(entry->key);
2589 if (existing_entry) {
2590 add_node_error(g, node,
2591 buf_sprintf("import of function '%s' overrides existing definition",
2592 buf_ptr(&fn_entry->proto_node->data.fn_proto.name)));
2593 } else {
2594 import->fn_table.put(entry->key, entry->value);
2595 }
2596 }
2597 }
2598 }
2599
2600 // import all the public types
2601 {
2602 auto it = target_import->type_table.entry_iterator();
2603 for (;;) {
2604 auto *entry = it.next();
2605 if (!entry)
2606 break;
2607
2608 TypeTableEntry *type_entry = entry->value;
2609 if (type_entry->id == TypeTableEntryIdStruct) {
2610 AstNode *decl_node = type_entry->data.structure.decl_node;
2611 bool is_pub = (decl_node->data.struct_decl.visib_mod != VisibModPrivate);
2612 if (is_pub) {
2613 auto existing_entry = import->type_table.maybe_get(entry->key);
2614 if (existing_entry) {
2615 add_node_error(g, node,
2616 buf_sprintf("import of type '%s' overrides existing definition",
2617 buf_ptr(&type_entry->name)));
2618 } else {
2619 import->type_table.put(entry->key, entry->value);
2620 }
2621 }
2622 }
2623 }
2624 }
2625
2626 // import all the public variables
2627 {
2628 auto it = target_import->block_context->variable_table.entry_iterator();
2629 for (;;) {
2630 auto *entry = it.next();
2631 if (!entry)
2632 break;
2633
2634 VariableTableEntry *var = entry->value;
2635 bool is_pub = (var->decl_node->data.variable_declaration.visib_mod != VisibModPrivate);
2636 if (is_pub) {
2637 auto existing_entry = import->type_table.maybe_get(entry->key);
2638 if (existing_entry) {
2639 add_node_error(g, node,
2640 buf_sprintf("import of variable '%s' overrides existing definition",
2641 buf_ptr(&var->name)));
2642 } else {
2643 import->block_context->variable_table.put(entry->key, entry->value);
2644 }
2645 }
2646 }
2647 }
2648 break;
2649 }
2597 // already took care of this
2598 break;
26502599 case NodeTypeStructDecl:
26512600 {
26522601 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
......@@ -2869,9 +2818,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
28692818 StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;
28702819
28712820 Buf *name = &node->data.struct_decl.name;
2872 auto table_entry = import->type_table.maybe_get(name);
2821 auto table_entry = g->primitive_type_table.maybe_get(name);
28732822 if (!table_entry) {
2874 table_entry = g->primitive_type_table.maybe_get(name);
2823 table_entry = import->type_table.maybe_get(name);
28752824 }
28762825 if (table_entry) {
28772826 struct_codegen->type_entry = table_entry->value;
......@@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
28902839 // this type is incomplete until we do another pass
28912840 import->type_table.put(&entry->name, entry);
28922841 struct_codegen->type_entry = entry;
2842
2843 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
2844 if (is_pub) {
2845 for (int i = 0; i < import->importers.length; i += 1) {
2846 ImporterInfo importer = import->importers.at(i);
2847 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
2848 if (table_entry) {
2849 add_node_error(g, importer.source_node,
2850 buf_sprintf("import of type '%s' overrides existing definition",
2851 buf_ptr(&entry->name)));
2852 } else {
2853 importer.import->type_table.put(&entry->name, entry);
2854 }
2855 }
2856 }
28932857 }
28942858
28952859 // determine which other top level declarations this struct depends on.
......@@ -2977,7 +2941,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
29772941 resolve_top_level_decl(g, import, node);
29782942 break;
29792943 case NodeTypeUse:
2980 // nothing to do
2944 // already taken care of
29812945 break;
29822946 case NodeTypeDirective:
29832947 case NodeTypeParamDecl:
......@@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
30543018static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
30553019 assert(node->type == NodeTypeRoot);
30563020
3057 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
3058 AstNode *child = node->data.root.top_level_decls.at(i);
3059 detect_top_level_decl_deps(g, import, child);
3060 }
3061
30623021 while (g->unresolved_top_level_decls.size() > 0) {
30633022 // for the sake of determinism, find the element with the lowest
30643023 // insert index and resolve that one.
......@@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A
30953054}
30963055
30973056void semantic_analyze(CodeGen *g) {
3057 {
3058 auto it = g->import_table.entry_iterator();
3059 for (;;) {
3060 auto *entry = it.next();
3061 if (!entry)
3062 break;
3063
3064 ImportTableEntry *import = entry->value;
3065
3066 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
3067 AstNode *child = import->root->data.root.top_level_decls.at(i);
3068 if (child->type == NodeTypeUse) {
3069 for (int i = 0; i < child->data.use.directives->length; i += 1) {
3070 AstNode *directive_node = child->data.use.directives->at(i);
3071 Buf *name = &directive_node->data.directive.name;
3072 add_node_error(g, directive_node,
3073 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
3074 }
3075
3076 ImportTableEntry *target_import = child->codegen_node->data.import_node.import;
3077 assert(target_import);
3078
3079 target_import->importers.append({import, child});
3080 }
3081 }
3082 }
3083 }
3084 {
3085 auto it = g->import_table.entry_iterator();
3086 for (;;) {
3087 auto *entry = it.next();
3088 if (!entry)
3089 break;
3090
3091 ImportTableEntry *import = entry->value;
3092
3093 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
3094 AstNode *child = import->root->data.root.top_level_decls.at(i);
3095 detect_top_level_decl_deps(g, import, child);
3096 }
3097 }
3098 }
30983099 {
30993100 auto it = g->import_table.entry_iterator();
31003101 for (;;) {
src/analyze.hpp+6
......@@ -105,6 +105,11 @@ struct TypeTableEntry {
105105
106106};
107107
108struct ImporterInfo {
109 ImportTableEntry *import;
110 AstNode *source_node;
111};
112
108113struct ImportTableEntry {
109114 AstNode *root;
110115 Buf *path; // relative to root_source_dir
......@@ -112,6 +117,7 @@ struct ImportTableEntry {
112117 Buf *source_code;
113118 ZigList<int> *line_offsets;
114119 BlockContext *block_context;
120 ZigList<ImporterInfo> importers;
115121
116122 // reminder: hash tables must be initialized before use
117123 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
test/run_tests.cpp+1
......@@ -994,6 +994,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
994994
995995 add_simple_case("order-independent declarations", R"SOURCE(
996996use "std.zig";
997const z : #typeof(stdin_fileno) = 0;
997998const x : #typeof(y) = 1234;
998999const y : u16 = 5678;
9991000pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {