aboutsummaryrefslogtreecommitdiff
path: root/boot/semantic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/semantic.cc')
-rw-r--r--boot/semantic.cc279
1 files changed, 53 insertions, 226 deletions
diff --git a/boot/semantic.cc b/boot/semantic.cc
index 0530448..42b7b3c 100644
--- a/boot/semantic.cc
+++ b/boot/semantic.cc
@@ -96,54 +96,26 @@ namespace elna::boot
{
}
- void type_analysis_visitor::visit(procedure_declaration *definition)
+ void type_analysis_visitor::visit(procedure_declaration *declaration)
{
- if (definition->body.has_value() && definition->heading().return_type.proper_type != nullptr)
+ this->returns = false;
+ walking_visitor::visit(declaration);
+
+ if (declaration->body.has_value())
{
- for (statement *const statement : definition->body.value().body())
+ if (!this->returns && declaration->heading().return_type.proper_type != nullptr)
{
- statement->accept(this);
- }
- if (!this->returns)
- {
- add_error<return_error>(definition->identifier.name, definition->position());
+ add_error<return_error>(declaration->identifier.name, declaration->position());
}
}
}
- void type_analysis_visitor::visit(assign_statement *)
- {
- }
-
- void type_analysis_visitor::visit(if_statement *)
- {
- }
-
- void type_analysis_visitor::visit(while_statement *)
- {
- }
-
- void type_analysis_visitor::visit(return_statement *)
+ void type_analysis_visitor::visit(return_statement *statement)
{
+ walking_visitor::visit(statement);
this->returns = true;
}
- void type_analysis_visitor::visit(defer_statement *)
- {
- }
-
- void type_analysis_visitor::visit(empty_statement *)
- {
- }
-
- void type_analysis_visitor::visit(case_statement *)
- {
- }
-
- void type_analysis_visitor::visit(procedure_call *)
- {
- }
-
bool type_analysis_visitor::check_unresolved_symbol(std::shared_ptr<alias_type> alias,
std::vector<std::string>& alias_path)
{
@@ -160,28 +132,32 @@ namespace elna::boot
return true;
}
- void type_analysis_visitor::visit(unit *unit)
+ void type_analysis_visitor::visit(type_declaration *declaration)
{
- for (type_declaration *const type : unit->types)
+ std::vector<std::string> alias_path;
+ auto unresolved_type = this->bag.lookup(declaration->identifier.name)->is_type()->symbol.get<alias_type>();
+
+ if (!check_unresolved_symbol(unresolved_type, alias_path))
{
- type->accept(this);
+ add_error<cyclic_declaration_error>(alias_path, declaration->position());
}
- for (procedure_declaration *const procedure : unit->procedures)
+ else
{
- this->returns = false;
- procedure->accept(this);
+ walking_visitor::visit(declaration);
}
}
- void type_analysis_visitor::visit(type_declaration *definition)
+ void type_analysis_visitor::visit(record_type_expression *expression)
{
- 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))
+ if (expression->base.has_value())
{
- add_error<cyclic_declaration_error>(alias_path, definition->position());
+ type base_type = inner_aliased_type(this->bag.lookup(expression->base.value())->is_type()->symbol);
+ if (base_type.get<record_type>() == nullptr)
+ {
+ add_error<base_type_error>(expression->base.value(), expression->position());
+ }
}
+ walking_visitor::visit(expression);
}
name_analysis_visitor::name_analysis_visitor(symbol_bag bag)
@@ -222,29 +198,25 @@ namespace elna::boot
return result_type;
}
- void name_analysis_visitor::visit(type_declaration *definition)
+ void name_analysis_visitor::visit(type_declaration *declaration)
{
- definition->body().accept(this);
- auto resolved = this->bag.resolve(definition->identifier.name, this->current_type);
+ walking_visitor::visit(declaration);
+ auto resolved = this->bag.resolve(declaration->identifier.name, this->current_type);
auto info = std::make_shared<type_info>(type(resolved));
- info->exported = definition->identifier.exported;
- this->bag.enter(definition->identifier.name, info);
- }
-
- void name_analysis_visitor::visit(type_expression *)
- {
+ info->exported = declaration->identifier.exported;
+ this->bag.enter(declaration->identifier.name, info);
}
void name_analysis_visitor::visit(pointer_type_expression *expression)
{
- expression->base().accept(this);
+ walking_visitor::visit(expression);
this->current_type = type(std::make_shared<pointer_type>(this->current_type));
}
void name_analysis_visitor::visit(array_type_expression *expression)
{
- expression->base().accept(this);
+ walking_visitor::visit(expression);
auto result_type = std::make_shared<array_type>(this->current_type, expression->size);
this->current_type = type(result_type);
@@ -350,9 +322,9 @@ namespace elna::boot
void name_analysis_visitor::visit(variable_declaration *declaration)
{
- declaration->variable_type().accept(this);
+ walking_visitor::visit(declaration);
- for (const auto& variable_identifier : declaration->identifiers)
+ for (const identifier_definition& variable_identifier : declaration->identifiers)
{
auto variable_symbol = register_variable(variable_identifier.name, declaration->is_extern,
declaration->position());
@@ -360,21 +332,21 @@ namespace elna::boot
}
}
- void name_analysis_visitor::visit(constant_declaration *definition)
+ void name_analysis_visitor::visit(constant_declaration *declaration)
{
- definition->body().accept(this);
+ walking_visitor::visit(declaration);
auto constant_symbol = std::make_shared<constant_info>(this->current_literal);
- constant_symbol->exported = definition->identifier.exported;
- this->bag.enter(definition->identifier.name, constant_symbol);
+ constant_symbol->exported = declaration->identifier.exported;
+ this->bag.enter(declaration->identifier.name, constant_symbol);
}
- void name_analysis_visitor::visit(procedure_declaration *definition)
+ void name_analysis_visitor::visit(procedure_declaration *declaration)
{
std::shared_ptr<procedure_info> info;
- auto [heading, parameter_names] = build_procedure(definition->heading());
+ auto [heading, parameter_names] = build_procedure(declaration->heading());
- if (definition->body.has_value())
+ if (declaration->body.has_value())
{
info = std::make_shared<procedure_info>(heading, std::move(parameter_names), this->bag.enter());
auto name_iterator = std::cbegin(info->names);
@@ -383,21 +355,21 @@ namespace elna::boot
while (name_iterator != std::cend(info->names) && type_iterator != std::cend(heading.parameters))
{
this->current_type = *type_iterator;
- auto variable_symbol = register_variable(*name_iterator, false, definition->heading().position());
+ auto variable_symbol = register_variable(*name_iterator, false, declaration->heading().position());
variable_symbol->exported = false;
++name_iterator;
++type_iterator;
}
- for (constant_declaration *const constant : definition->body.value().constants())
+ for (constant_declaration *const constant : declaration->body.value().constants())
{
constant->accept(this);
}
- for (variable_declaration *const variable : definition->body.value().variables())
+ for (variable_declaration *const variable : declaration->body.value().variables())
{
variable->accept(this);
}
- for (statement *const statement : definition->body.value().body())
+ for (statement *const statement : declaration->body.value().statements())
{
statement->accept(this);
}
@@ -407,101 +379,8 @@ namespace elna::boot
{
info = std::make_shared<procedure_info>(heading, std::move(parameter_names));
}
- info->exported = definition->identifier.exported;
- this->bag.enter(definition->identifier.name, info);
- }
-
- void name_analysis_visitor::visit(assign_statement *statement)
- {
- statement->lvalue().accept(this);
- statement->rvalue().accept(this);
- }
-
- void name_analysis_visitor::visit(if_statement *statement)
- {
- statement->body().prerequisite().accept(this);
- for (struct statement *const statement : statement->body().statements)
- {
- statement->accept(this);
- }
- for (const auto branch : statement->branches)
- {
- branch->prerequisite().accept(this);
-
- for (struct statement *const statement : branch->statements)
- {
- statement->accept(this);
- }
- }
- if (statement->alternative != nullptr)
- {
- for (struct statement *const statement : *statement->alternative)
- {
- statement->accept(this);
- }
- }
- }
-
- void name_analysis_visitor::visit(import_declaration *)
- {
- }
-
- void name_analysis_visitor::visit(while_statement *statement)
- {
- statement->body().prerequisite().accept(this);
- for (struct statement *const statement : statement->body().statements)
- {
- statement->accept(this);
- }
- for (const auto branch : statement->branches)
- {
- branch->prerequisite().accept(this);
-
- for (struct statement *const statement : branch->statements)
- {
- statement->accept(this);
- }
- }
- }
-
- void name_analysis_visitor::visit(return_statement *statement)
- {
- statement->return_expression().accept(this);
- }
-
- void name_analysis_visitor::visit(defer_statement *statement)
- {
- for (struct statement *const statement : statement->statements)
- {
- statement->accept(this);
- }
- }
-
- void name_analysis_visitor::visit(empty_statement *)
- {
- }
-
- void name_analysis_visitor::visit(case_statement *statement)
- {
- statement->condition().accept(this);
- for (const switch_case& case_block : statement->cases)
- {
- for (expression *const case_label : case_block.labels)
- {
- case_label->accept(this);
- }
- for (struct statement *const statement : case_block.statements)
- {
- statement->accept(this);
- }
- }
- if (statement->alternative != nullptr)
- {
- for (struct statement *const statement : *statement->alternative)
- {
- statement->accept(this);
- }
- }
+ info->exported = declaration->identifier.exported;
+ this->bag.enter(declaration->identifier.name, info);
}
void name_analysis_visitor::visit(procedure_call *call)
@@ -536,7 +415,7 @@ namespace elna::boot
{
procedure->accept(this);
}
- if (unit->body.has_value())
+ if (unit->entry_point.has_value())
{
this->bag.enter();
auto variable_type = this->bag.lookup("Int")->is_type()->symbol;
@@ -547,7 +426,7 @@ namespace elna::boot
variable_type = type(std::make_shared<pointer_type>(variable_type));
this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false));
- for (statement *const statement : unit->body.value())
+ for (statement *const statement : unit->entry_point.value())
{
statement->accept(this);
}
@@ -566,22 +445,10 @@ namespace elna::boot
void name_analysis_visitor::visit(cast_expression *expression)
{
- expression->value().accept(this);
- expression->target().accept(this);
+ walking_visitor::visit(expression);
expression->expression_type = this->current_type;
}
- void name_analysis_visitor::visit(binary_expression *expression)
- {
- expression->lhs().accept(this);
- expression->rhs().accept(this);
- }
-
- void name_analysis_visitor::visit(unary_expression *expression)
- {
- expression->operand().accept(this);
- }
-
void name_analysis_visitor::visit(named_expression *expression)
{
if (auto unresolved_alias = this->bag.declared(expression->name))
@@ -602,22 +469,6 @@ namespace elna::boot
}
}
- void name_analysis_visitor::visit(array_access_expression *expression)
- {
- expression->base().accept(this);
- expression->index().accept(this);
- }
-
- void name_analysis_visitor::visit(field_access_expression *expression)
- {
- expression->base().accept(this);
- }
-
- void name_analysis_visitor::visit(dereference_expression *expression)
- {
- expression->base().accept(this);
- }
-
void name_analysis_visitor::visit(literal<std::int32_t> *literal)
{
this->current_literal = literal->value;
@@ -672,39 +523,15 @@ namespace elna::boot
{
type->accept(this);
}
- for (variable_declaration *const variable : unit->variables)
- {
- variable->accept(this);
- }
- for (procedure_declaration *const procedure : unit->procedures)
- {
- procedure->accept(this);
- }
}
- void declaration_visitor::visit(type_declaration *definition)
+ void declaration_visitor::visit(type_declaration *declaration)
{
- const std::string& type_identifier = definition->identifier.name;
+ const std::string& type_identifier = declaration->identifier.name;
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second)
{
- add_error<already_declared_error>(definition->identifier.name, definition->position());
- }
- }
-
- void declaration_visitor::visit(variable_declaration *)
- {
- }
-
- void declaration_visitor::visit(procedure_declaration *definition)
- {
- if (!definition->body.has_value())
- {
- return;
- }
- for (variable_declaration *const variable : definition->body.value().variables())
- {
- variable->accept(this);
+ add_error<already_declared_error>(declaration->identifier.name, declaration->position());
}
}
}