| ... | ... | @@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, |
| 807 | 807 | if (fn_def_node) { |
| 808 | 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 | 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 | 1729 | variable_entry->is_ptr = true; |
| 1716 | 1730 | variable_entry->decl_node = source_node; |
| 1717 | 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 | 1749 | return variable_entry; |
| 1719 | 1750 | } |
| 1720 | 1751 | return nullptr; |
| ... | ... | @@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2563 | 2594 | // already looked at these in the preview pass |
| 2564 | 2595 | break; |
| 2565 | 2596 | 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; |
| 2650 | 2599 | case NodeTypeStructDecl: |
| 2651 | 2600 | { |
| 2652 | 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 | 2818 | StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node; |
| 2870 | 2819 | |
| 2871 | 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 | 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 | 2825 | if (table_entry) { |
| 2877 | 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 | 2839 | // this type is incomplete until we do another pass |
| 2891 | 2840 | import->type_table.put(&entry->name, entry); |
| 2892 | 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 | 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 | 2941 | resolve_top_level_decl(g, import, node); |
| 2978 | 2942 | break; |
| 2979 | 2943 | case NodeTypeUse: |
| 2980 | | // nothing to do |
| 2944 | // already taken care of |
| 2981 | 2945 | break; |
| 2982 | 2946 | case NodeTypeDirective: |
| 2983 | 2947 | case NodeTypeParamDecl: |
| ... | ... | @@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 3054 | 3018 | static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 3055 | 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 | 3021 | while (g->unresolved_top_level_decls.size() > 0) { |
| 3063 | 3022 | // for the sake of determinism, find the element with the lowest |
| 3064 | 3023 | // insert index and resolve that one. |
| ... | ... | @@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A |
| 3095 | 3054 | } |
| 3096 | 3055 | |
| 3097 | 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 | 3100 | auto it = g->import_table.entry_iterator(); |
| 3100 | 3101 | for (;;) { |