Document symbol bag class and methods

This commit is contained in:
2025-08-23 00:48:58 +02:00
parent 809e41bcc3
commit fd3729ba16
13 changed files with 294 additions and 117 deletions

View File

@@ -93,8 +93,8 @@ namespace elna::boot
return "Only one variable can be initialized";
}
type_analysis_visitor::type_analysis_visitor(const char *path)
: error_container(path)
type_analysis_visitor::type_analysis_visitor(const char *path, symbol_bag bag)
: error_container(path), bag(bag)
{
}
@@ -113,7 +113,7 @@ namespace elna::boot
}
if (!this->returns)
{
add_error<return_error>(definition->identifier.identifier, this->input_file, definition->position());
add_error<return_error>(definition->identifier.name, this->input_file, definition->position());
}
}
}
@@ -126,10 +126,6 @@ namespace elna::boot
{
}
void type_analysis_visitor::visit(import_declaration *)
{
}
void type_analysis_visitor::visit(while_statement *)
{
}
@@ -151,8 +147,28 @@ namespace elna::boot
{
}
bool type_analysis_visitor::check_unresolved_symbol(std::shared_ptr<alias_type> alias,
std::vector<std::string>& alias_path)
{
if (std::find(std::cbegin(alias_path), std::cend(alias_path), alias->name) != std::cend(alias_path))
{
return false;
}
alias_path.push_back(alias->name);
if (auto another_alias = alias->reference.get<alias_type>())
{
return check_unresolved_symbol(another_alias, alias_path);
}
return true;
}
void type_analysis_visitor::visit(unit *unit)
{
for (type_declaration *const type : unit->types)
{
type->accept(this);
}
for (procedure_declaration *const procedure : unit->procedures)
{
this->returns = false;
@@ -160,6 +176,17 @@ namespace elna::boot
}
}
void type_analysis_visitor::visit(type_declaration *definition)
{
std::vector<std::string> alias_path;
auto unresolved_type = this->bag.lookup(definition->identifier.name)->is_type()->symbol.get<alias_type>();
if (!check_unresolved_symbol(unresolved_type, alias_path))
{
add_error<cyclic_declaration_error>(alias_path, this->input_file, definition->position());
}
}
name_analysis_visitor::name_analysis_visitor(const char *path, symbol_bag bag)
: error_container(path), bag(bag)
{
@@ -205,18 +232,20 @@ namespace elna::boot
void name_analysis_visitor::visit(type_declaration *definition)
{
definition->body().accept(this);
auto unresolved_declaration = this->bag.unresolved.at(definition->identifier.identifier);
auto resolved = this->bag.resolve(definition->identifier.name, this->current_type);
auto info = std::make_shared<type_info>(type(resolved));
unresolved_declaration->reference = this->current_type;
info->exported = definition->identifier.exported;
this->bag.enter(definition->identifier.name, info);
}
void name_analysis_visitor::visit(named_type_expression *type_expression)
{
auto unresolved_alias = this->bag.unresolved.find(type_expression->name);
auto unresolved_alias = this->bag.declared(type_expression->name);
if (unresolved_alias != this->bag.unresolved.end())
if (unresolved_alias != nullptr)
{
this->current_type = type(unresolved_alias->second);
this->current_type = type(unresolved_alias);
}
else if (auto from_symbol_table = this->bag.lookup(type_expression->name))
{
@@ -301,15 +330,24 @@ namespace elna::boot
for (const auto& variable_identifier : declaration->identifiers)
{
this->bag.enter(variable_identifier.identifier, std::make_shared<variable_info>(this->current_type));
auto variable_symbol = std::make_shared<variable_info>(this->current_type, declaration->is_extern);
variable_symbol->exported = variable_identifier.exported;
if (!this->bag.enter(variable_identifier.name, variable_symbol))
{
add_error<already_declared_error>(variable_identifier.name, this->input_file,
declaration->position());
}
}
}
void name_analysis_visitor::visit(constant_declaration *definition)
{
definition->body().accept(this);
auto constant_symbol = std::make_shared<constant_info>(this->current_literal);
this->bag.enter(definition->identifier.identifier, std::make_shared<constant_info>(this->current_literal));
constant_symbol->exported = definition->identifier.exported;
this->bag.enter(definition->identifier.name, constant_symbol);
}
void name_analysis_visitor::visit(procedure_declaration *definition)
@@ -339,7 +377,8 @@ namespace elna::boot
{
info = std::make_shared<procedure_info>(heading, definition->parameter_names);
}
this->bag.enter(definition->identifier.identifier, info);
info->exported = definition->identifier.exported;
this->bag.enter(definition->identifier.name, info);
}
void name_analysis_visitor::visit(assign_statement *statement)
@@ -440,42 +479,12 @@ namespace elna::boot
}
}
bool name_analysis_visitor::check_unresolved_symbol(std::shared_ptr<alias_type> alias,
std::vector<std::string>& path)
{
if (std::find(std::cbegin(path), std::cend(path), alias->name) != std::cend(path))
{
return false;
}
path.push_back(alias->name);
if (auto another_alias = alias->reference.get<alias_type>())
{
return check_unresolved_symbol(another_alias, path);
}
return true;
}
void name_analysis_visitor::visit(unit *unit)
{
for (type_declaration *const type : unit->types)
{
type->accept(this);
}
for (auto& unresolved : this->bag.unresolved)
{
std::vector<std::string> path;
if (check_unresolved_symbol(unresolved.second, path))
{
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
this->bag.enter(unresolved.first, info);
}
else
{
add_error<cyclic_declaration_error>(path, this->input_file, position{ 0, 0 });
}
}
for (variable_declaration *const variable : unit->variables)
{
variable->accept(this);
@@ -590,12 +599,7 @@ namespace elna::boot
}
for (type_declaration *const type : unit->types)
{
const std::string& type_identifier = type->identifier.identifier;
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second)
{
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
}
type->accept(this);
}
for (variable_declaration *const variable : unit->variables)
{
@@ -607,6 +611,17 @@ namespace elna::boot
}
}
void declaration_visitor::visit(type_declaration *definition)
{
const std::string& type_identifier = definition->identifier.name;
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second)
{
add_error<already_declared_error>(definition->identifier.name, this->input_file,
definition->position());
}
}
void declaration_visitor::visit(variable_declaration *declaration)
{
if (declaration->has_initializer() && declaration->identifiers.size() > 1)