aboutsummaryrefslogtreecommitdiff
path: root/boot/name_analysis.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/name_analysis.cc')
-rw-r--r--boot/name_analysis.cc55
1 files changed, 42 insertions, 13 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 30d3cda..10b8a8d 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
declaration_error::declaration_error(const source_position position, const std::string& name, payload_type payload)
- : diagnostic(position), name(name), payload(payload)
+ : diagnostic(position), name(name), payload(std::move(payload))
{
}
@@ -57,11 +57,12 @@ namespace elna::boot
}, this->payload);
}
- std::optional<std::pair<std::string, source_position>> declaration_error::note() const
+ std::optional<diagnostic_note> declaration_error::note() const
{
if (std::holds_alternative<redefinition>(this->payload))
{
- return previous_declaration_note(std::get<redefinition>(this->payload).original);
+ return previous_declaration_note(std::get<redefinition>(this->payload).original,
+ "previously declared here", std::get<redefinition>(this->payload).file);
}
else
{
@@ -99,7 +100,7 @@ namespace elna::boot
}, this->payload);
}
- std::optional<std::pair<std::string, source_position>> const_qualifier_error::note() const
+ std::optional<diagnostic_note> const_qualifier_error::note() const
{
if (std::holds_alternative<not_initialized>(this->payload))
{
@@ -175,7 +176,7 @@ namespace elna::boot
}, payload);
}
- std::optional<std::pair<std::string, source_position>> member_error::note() const
+ std::optional<diagnostic_note> member_error::note() const
{
if (std::holds_alternative<duplicate>(this->payload))
{
@@ -201,8 +202,9 @@ namespace elna::boot
}
}
- name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target)
- : bag(std::move(bag)), constant_evaluator(this->bag, target)
+ name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target,
+ std::filesystem::path module_file)
+ : bag(std::move(bag)), constant_evaluator(this->bag, target), module_file(std::move(module_file))
{
}
@@ -295,7 +297,15 @@ namespace elna::boot
info->exported = declaration->identifier.exported();
info->position.emplace(declaration->position());
- this->bag.enter(declaration->identifier.name(), info);
+ info->file = this->module_file;
+
+ if (!this->bag.enter(declaration->identifier.name(), info))
+ {
+ auto original = this->bag.lookup(declaration->identifier.name());
+ add_error<declaration_error>(declaration->identifier.id().position(), declaration->identifier.name(),
+ declaration_error::redefinition{ .original = original->position,
+ .file = this->redefinition_file(original) });
+ }
}
void name_analysis_visitor::visit(pointer_type_expression *expression)
@@ -542,17 +552,25 @@ namespace elna::boot
this->current_type = type(result_type);
}
+ std::filesystem::path name_analysis_visitor::redefinition_file(
+ const std::shared_ptr<info>& original) const
+ {
+ return original->file != this->module_file ? original->file : std::filesystem::path{};
+ }
+
std::shared_ptr<variable_info> name_analysis_visitor::register_variable(const std::string& name,
const bool is_extern, const source_position position)
{
auto variable_symbol = std::make_shared<variable_info>(this->current_type, is_extern);
variable_symbol->position.emplace(position);
+ variable_symbol->file = this->module_file;
if (!this->bag.enter(name, variable_symbol))
{
auto original = this->bag.lookup(name);
add_error<declaration_error>(position, name,
- declaration_error::redefinition{ .original = original->position });
+ declaration_error::redefinition{ .original = original->position,
+ .file = this->redefinition_file(original) });
}
return variable_symbol;
}
@@ -631,7 +649,14 @@ namespace elna::boot
}
info->exported = declaration->identifier.exported();
info->position.emplace(declaration->position());
- this->bag.enter(declaration->identifier.name(), info);
+ info->file = this->module_file;
+ if (!this->bag.enter(declaration->identifier.name(), info))
+ {
+ auto original = this->bag.lookup(declaration->identifier.name());
+ add_error<declaration_error>(declaration->identifier.id().position(), declaration->identifier.name(),
+ declaration_error::redefinition{ .original = original->position,
+ .file = this->redefinition_file(original) });
+ }
}
void name_analysis_visitor::visit(procedure_call *call)
@@ -666,12 +691,16 @@ namespace elna::boot
{
this->bag.enter();
auto variable_type = lookup_primitive_type("Int");
- this->bag.enter("count", std::make_shared<variable_info>(variable_type, false));
+ auto count_symbol = std::make_shared<variable_info>(variable_type, false);
+ count_symbol->file = this->module_file;
+ this->bag.enter("count", count_symbol);
variable_type = lookup_primitive_type("Word8");
variable_type = type(std::make_shared<pointer_type>(variable_type));
variable_type = type(std::make_shared<pointer_type>(variable_type));
- this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false));
+ auto parameters_symbol = std::make_shared<variable_info>(variable_type, false);
+ parameters_symbol->file = this->module_file;
+ this->bag.enter("parameters", parameters_symbol);
for (statement *const statement : unit->entry_point)
{
@@ -971,7 +1000,7 @@ namespace elna::boot
{
add_error<declaration_error>(declaration->identifier.id().position(),
declaration->identifier.id().name(),
- declaration_error::redefinition{ .original = declaration->position() });
+ declaration_error::redefinition{ .original = declaration->position(), .file = {} });
}
}