diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-25 23:41:18 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-25 23:41:18 +0200 |
| commit | 81370291c039593a9886c7b3f776ca55a2858f0d (patch) | |
| tree | 47e12c5263e7784d3f0fc75fbbf6d791291e2230 /boot/dependency.cc | |
| parent | df51f9c4ee0ee4ac22206513bcd60e6928b7eaeb (diff) | |
| download | elna-81370291c039593a9886c7b3f776ca55a2858f0d.tar.gz | |
Reject circular imports
Diffstat (limited to 'boot/dependency.cc')
| -rw-r--r-- | boot/dependency.cc | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/boot/dependency.cc b/boot/dependency.cc index 4590513..7f87e40 100644 --- a/boot/dependency.cc +++ b/boot/dependency.cc @@ -26,6 +26,17 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { + circular_import_error::circular_import_error(const source_position position, + const std::string& module_name) + : diagnostic(position), module_name(module_name) + { + } + + std::string circular_import_error::what() const + { + return "Circular import of module '" + this->module_name + "'"; + } + dependency read_source(std::istream& entry_point, const target_info& target) { driver parse_driver; @@ -35,58 +46,66 @@ namespace elna::boot dependency outcome; if (parser() != 0) { - std::swap(outcome.errors(), parse_driver.errors()); + std::swap(outcome.errors, parse_driver.errors()); return outcome; } else { - std::swap(outcome.tree, parse_driver.tree); + std::swap(outcome.value, parse_driver.tree); } materialization_visitor materialization_visitor(target); - outcome.tree->accept(&materialization_visitor); + outcome.value->accept(&materialization_visitor); if (materialization_visitor.has_errors()) { - std::swap(outcome.errors(), materialization_visitor.errors()); - return outcome; + std::swap(outcome.errors, materialization_visitor.errors()); + outcome.value.reset(); } - declaration_visitor declaration_visitor{}; - outcome.tree->accept(&declaration_visitor); - - if (declaration_visitor.has_errors()) - { - std::swap(outcome.errors(), declaration_visitor.errors()); - } - outcome.unresolved = declaration_visitor.unresolved; - return outcome; } - diagnostic_list analyze_semantics(std::unique_ptr<unit>& tree, symbol_bag& bag, - const target_info& target) + analysis_result analyze_semantics(std::unique_ptr<unit>& tree, + const std::vector<std::shared_ptr<symbol_table>>& imports, + const std::shared_ptr<symbol_table>& globals, const target_info& target) { - name_analysis_visitor name_analyser(bag, target); + declaration_visitor declarations{}; + tree->accept(&declarations); + analysis_result result{ .value = { std::move(declarations.unresolved), globals }, .errors = {} }; + + if (declarations.has_errors()) + { + std::swap(result.errors, declarations.errors()); + return result; + } + for (const auto& import : imports) + { + result.value.add_import(import); + } + name_analysis_visitor name_analyser(result.value, target); tree->accept(&name_analyser); if (name_analyser.has_errors()) { - return std::move(name_analyser.errors()); + std::swap(result.errors, name_analyser.errors()); + return result; } - type_analysis_visitor type_analyzer(bag, target); + type_analysis_visitor type_analyzer(result.value, target); tree->accept(&type_analyzer); if (type_analyzer.has_errors()) { - return std::move(type_analyzer.errors()); + std::swap(result.errors, type_analyzer.errors()); + return result; } - validation_visitor validator(bag, target); + validation_visitor validator(result.value, target); tree->accept(&validator); if (validator.has_errors()) { - return std::move(validator.errors()); + std::swap(result.errors, validator.errors()); + return result; } - return diagnostic_list{}; + return result; } std::filesystem::path build_path(const std::vector<std::string>& segments) |
