| ... | @@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, | ... | @@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 807 | if (fn_def_node) { | 807 | if (fn_def_node) { |
| 808 | preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry); | 808 | preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry); |
| 809 | } | 809 | } |
| | 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 | } |
| 810 | } | 824 | } |
| 811 | | 825 | |
| 812 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 826 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| ... | @@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa | ... | @@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 1715 | variable_entry->is_ptr = true; | 1729 | variable_entry->is_ptr = true; |
| 1716 | variable_entry->decl_node = source_node; | 1730 | variable_entry->decl_node = source_node; |
| 1717 | context->variable_table.put(&variable_entry->name, variable_entry); | 1731 | 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 | |
| 1718 | return variable_entry; | 1749 | return variable_entry; |
| 1719 | } | 1750 | } |
| 1720 | return nullptr; | 1751 | return nullptr; |
| ... | @@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2563 | // already looked at these in the preview pass | 2594 | // already looked at these in the preview pass |
| 2564 | break; | 2595 | break; |
| 2565 | case NodeTypeUse: | 2596 | case NodeTypeUse: |
| 2566 | { | 2597 | // already took care of this |
| 2567 | for (int i = 0; i < node->data.use.directives->length; i += 1) { | 2598 | break; |
| 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 | } | | |
| 2650 | case NodeTypeStructDecl: | 2599 | case NodeTypeStructDecl: |
| 2651 | { | 2600 | { |
| 2652 | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { | 2601 | 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 | ... | @@ -2869,9 +2818,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2869 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; | 2818 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; |
| 2870 | | 2819 | |
| 2871 | Buf *name = &node->data.struct_decl.name; | 2820 | 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); |
| 2873 | if (!table_entry) { | 2822 | if (!table_entry) { |
| 2874 | table_entry = g->primitive_type_table.maybe_get(name); | 2823 | table_entry = import->type_table.maybe_get(name); |
| 2875 | } | 2824 | } |
| 2876 | if (table_entry) { | 2825 | if (table_entry) { |
| 2877 | struct_codegen->type_entry = table_entry->value; | 2826 | struct_codegen->type_entry = table_entry->value; |
| ... | @@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2890 | // this type is incomplete until we do another pass | 2839 | // this type is incomplete until we do another pass |
| 2891 | import->type_table.put(&entry->name, entry); | 2840 | import->type_table.put(&entry->name, entry); |
| 2892 | struct_codegen->type_entry = entry; | 2841 | 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 | } |
| 2893 | } | 2857 | } |
| 2894 | | 2858 | |
| 2895 | // determine which other top level declarations this struct depends on. | 2859 | // 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 | ... | @@ -2977,7 +2941,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2977 | resolve_top_level_decl(g, import, node); | 2941 | resolve_top_level_decl(g, import, node); |
| 2978 | break; | 2942 | break; |
| 2979 | case NodeTypeUse: | 2943 | case NodeTypeUse: |
| 2980 | // nothing to do | 2944 | // already taken care of |
| 2981 | break; | 2945 | break; |
| 2982 | case NodeTypeDirective: | 2946 | case NodeTypeDirective: |
| 2983 | case NodeTypeParamDecl: | 2947 | case NodeTypeParamDecl: |
| ... | @@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 3054 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 3018 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 3055 | assert(node->type == NodeTypeRoot); | 3019 | assert(node->type == NodeTypeRoot); |
| 3056 | | 3020 | |
| 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 | | | |
| 3062 | while (g->unresolved_top_level_decls.size() > 0) { | 3021 | while (g->unresolved_top_level_decls.size() > 0) { |
| 3063 | // for the sake of determinism, find the element with the lowest | 3022 | // for the sake of determinism, find the element with the lowest |
| 3064 | // insert index and resolve that one. | 3023 | // insert index and resolve that one. |
| ... | @@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A | ... | @@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A |
| 3095 | } | 3054 | } |
| 3096 | | 3055 | |
| 3097 | void semantic_analyze(CodeGen *g) { | 3056 | void 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 | } |
| 3098 | { | 3099 | { |
| 3099 | auto it = g->import_table.entry_iterator(); | 3100 | auto it = g->import_table.entry_iterator(); |
| 3100 | for (;;) { | 3101 | for (;;) { |