aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-25 23:41:18 +0200
committerEugen Wissner <belka@caraus.de>2026-08-25 23:41:18 +0200
commit81370291c039593a9886c7b3f776ca55a2858f0d (patch)
tree47e12c5263e7784d3f0fc75fbbf6d791291e2230 /boot
parentdf51f9c4ee0ee4ac22206513bcd60e6928b7eaeb (diff)
downloadelna-81370291c039593a9886c7b3f776ca55a2858f0d.tar.gz
Reject circular imports
Diffstat (limited to 'boot')
-rw-r--r--boot/dependency.cc65
-rw-r--r--boot/symbol.cc4
2 files changed, 44 insertions, 25 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)
diff --git a/boot/symbol.cc b/boot/symbol.cc
index b32782e..fcafae4 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -409,9 +409,9 @@ namespace elna::boot
return unresolved_declaration;
}
- void symbol_bag::add_import(const symbol_bag& bag)
+ void symbol_bag::add_import(const std::shared_ptr<symbol_table>& symbols)
{
- this->imports.push_front(bag.exported_symbols());
+ this->imports.push_front(symbols);
}
bool symbol_bag::is_global() const