aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/ast.cc426
-rw-r--r--boot/parser.yy25
-rw-r--r--boot/semantic.cc279
-rw-r--r--boot/symbol.cc17
4 files changed, 423 insertions, 324 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index b6ce4b3..4270a3b 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -24,11 +24,6 @@ namespace elna::boot
__builtin_unreachable();
}
- void empty_visitor::visit(type_expression *)
- {
- not_implemented();
- }
-
void empty_visitor::visit(array_type_expression *)
{
not_implemented();
@@ -204,6 +199,300 @@ namespace elna::boot
not_implemented();
}
+ void walking_visitor::visit(import_declaration *)
+ {
+ }
+
+ void walking_visitor::visit(procedure_declaration *declaration)
+ {
+ for (const field_declaration& parameter : declaration->heading().parameters)
+ {
+ parameter.second->accept(this);
+ }
+ if (declaration->heading().return_type.proper_type != nullptr)
+ {
+ declaration->heading().return_type.proper_type->accept(this);
+ }
+ if (declaration->body.has_value())
+ {
+ for (constant_declaration *const constant : declaration->body.value().constants())
+ {
+ constant->accept(this);
+ }
+ for (variable_declaration *const variable : declaration->body.value().variables())
+ {
+ variable->accept(this);
+ }
+ for (statement *const statement : declaration->body.value().statements())
+ {
+ statement->accept(this);
+ }
+ }
+ }
+
+ void walking_visitor::visit(assign_statement *statement)
+ {
+ statement->lvalue().accept(this);
+ statement->rvalue().accept(this);
+ }
+
+ void walking_visitor::visit(if_statement *statement)
+ {
+ statement->branch().prerequisite().accept(this);
+ for (struct statement *const branch_statement : statement->branch().statements)
+ {
+ branch_statement->accept(this);
+ }
+ for (conditional_statements *const branch : statement->branches)
+ {
+ branch->prerequisite().accept(this);
+
+ for (struct statement *const branch_statement : branch->statements)
+ {
+ branch_statement->accept(this);
+ }
+ }
+ if (statement->alternative != nullptr)
+ {
+ for (struct statement *const branch_statement : *statement->alternative)
+ {
+ branch_statement->accept(this);
+ }
+ }
+ }
+
+ void walking_visitor::visit(while_statement *statement)
+ {
+ statement->branch().prerequisite().accept(this);
+ for (struct statement *const branch_statement : statement->branch().statements)
+ {
+ branch_statement->accept(this);
+ }
+ for (conditional_statements *const branch : statement->branches)
+ {
+ branch->prerequisite().accept(this);
+
+ for (struct statement *const branch_statement : branch->statements)
+ {
+ branch_statement->accept(this);
+ }
+ }
+ }
+
+ void walking_visitor::visit(return_statement *statement)
+ {
+ statement->return_expression().accept(this);
+ }
+
+ void walking_visitor::visit(defer_statement *statement)
+ {
+ for (struct statement *const block_statement : statement->statements)
+ {
+ block_statement->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(empty_statement *)
+ {
+ }
+
+ void walking_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 block_statement : case_block.statements)
+ {
+ block_statement->accept(this);
+ }
+ }
+ if (statement->alternative != nullptr)
+ {
+ for (struct statement *const block_statement : *statement->alternative)
+ {
+ block_statement->accept(this);
+ }
+ }
+ }
+
+ void walking_visitor::visit(procedure_call *call)
+ {
+ call->callable().accept(this);
+ for (expression *const argument : call->arguments)
+ {
+ argument->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(unit *unit)
+ {
+ for (import_declaration *const _import : unit->imports)
+ {
+ _import->accept(this);
+ }
+ for (type_declaration *const type : unit->types)
+ {
+ type->accept(this);
+ }
+ for (variable_declaration *const variable : unit->variables)
+ {
+ variable->accept(this);
+ }
+ for (constant_declaration *const constant : unit->constants)
+ {
+ constant->accept(this);
+ }
+ for (procedure_declaration *const procedure : unit->procedures)
+ {
+ procedure->accept(this);
+ }
+ if (unit->entry_point.has_value())
+ {
+ for (statement *const entry_statement : unit->entry_point.value())
+ {
+ entry_statement->accept(this);
+ }
+ }
+ }
+
+ void walking_visitor::visit(type_declaration *declaration)
+ {
+ declaration->underlying_type().accept(this);
+ }
+
+ void walking_visitor::visit(variable_declaration *declaration)
+ {
+ declaration->variable_type().accept(this);
+ if (declaration->initializer != nullptr)
+ {
+ declaration->initializer->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(constant_declaration *declaration)
+ {
+ declaration->initializer().accept(this);
+ }
+
+ void walking_visitor::visit(array_type_expression *expression)
+ {
+ expression->base().accept(this);
+ }
+
+ void walking_visitor::visit(pointer_type_expression *expression)
+ {
+ expression->base().accept(this);
+ }
+
+ void walking_visitor::visit(record_type_expression *expression)
+ {
+ for (const field_declaration& field : expression->fields)
+ {
+ field.second->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(union_type_expression *expression)
+ {
+ for (const field_declaration& field : expression->fields)
+ {
+ field.second->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(procedure_type_expression *expression)
+ {
+ for (const field_declaration& field : expression->parameters)
+ {
+ field.second->accept(this);
+ }
+ if (expression->return_type.proper_type != nullptr)
+ {
+ expression->return_type.proper_type->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(enumeration_type_expression *)
+ {
+ }
+
+ void walking_visitor::visit(cast_expression *expression)
+ {
+ expression->value().accept(this);
+ expression->target().accept(this);
+ }
+
+ void walking_visitor::visit(traits_expression *trait)
+ {
+ if (!trait->parameters.empty())
+ {
+ trait->parameters.front()->accept(this);
+ }
+ }
+
+ void walking_visitor::visit(binary_expression *expression)
+ {
+ expression->lhs().accept(this);
+ expression->rhs().accept(this);
+ }
+
+ void walking_visitor::visit(unary_expression *expression)
+ {
+ expression->operand().accept(this);
+ }
+
+ void walking_visitor::visit(named_expression *)
+ {
+ }
+
+ void walking_visitor::visit(array_access_expression *expression)
+ {
+ expression->base().accept(this);
+ expression->index().accept(this);
+ }
+
+ void walking_visitor::visit(field_access_expression *expression)
+ {
+ expression->base().accept(this);
+ }
+
+ void walking_visitor::visit(dereference_expression *expression)
+ {
+ expression->base().accept(this);
+ }
+
+ void walking_visitor::visit(literal<std::int32_t> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<std::uint32_t> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<double> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<bool> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<unsigned char> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<std::nullptr_t> *)
+ {
+ }
+
+ void walking_visitor::visit(literal<std::string> *)
+ {
+ }
+
node::node(const struct position position)
: source_position(position)
{
@@ -288,43 +577,6 @@ namespace elna::boot
return nullptr;
}
- void type_expression::accept(parser_visitor *visitor)
- {
- if (named_expression *node = is_named())
- {
- return visitor->visit(node);
- }
- else if (array_type_expression *node = is_array())
- {
- return visitor->visit(node);
- }
- else if (pointer_type_expression *node = is_pointer())
- {
- return visitor->visit(node);
- }
- else if (record_type_expression *node = is_record())
- {
- return visitor->visit(node);
- }
- else if (union_type_expression *node = is_union())
- {
- return visitor->visit(node);
- }
- else if (procedure_type_expression *node = is_procedure())
- {
- return visitor->visit(node);
- }
- else if (enumeration_type_expression *node = is_enumeration())
- {
- return visitor->visit(node);
- }
- __builtin_unreachable();
- }
-
- type_expression::~type_expression()
- {
- }
-
array_type_expression::array_type_expression(const struct position position,
type_expression *base, const std::uint32_t size)
: node(position), m_base(base), size(size)
@@ -417,8 +669,8 @@ namespace elna::boot
variable_declaration::variable_declaration(const struct position position,
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
- expression *body)
- : node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), body(body)
+ expression *initializer)
+ : node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), initializer(initializer)
{
}
@@ -436,7 +688,7 @@ namespace elna::boot
bool variable_declaration::has_initializer() const
{
- return this->is_extern || this->body != nullptr;
+ return this->is_extern || this->initializer != nullptr;
}
type_expression& variable_declaration::variable_type()
@@ -450,8 +702,8 @@ namespace elna::boot
}
constant_declaration::constant_declaration(const struct position position, identifier_definition identifier,
- expression *body)
- : declaration(position, identifier), m_body(body)
+ expression *initializer)
+ : declaration(position, identifier), m_initializer(initializer)
{
}
@@ -460,14 +712,14 @@ namespace elna::boot
visitor->visit(this);
}
- expression& constant_declaration::body()
+ expression& constant_declaration::initializer()
{
- return *m_body;
+ return *m_initializer;
}
constant_declaration::~constant_declaration()
{
- delete m_body;
+ delete m_initializer;
}
procedure_type_expression::procedure_type_expression(const struct position position,
@@ -511,8 +763,9 @@ namespace elna::boot
}
procedure_declaration::procedure_declaration(const struct position position, identifier_definition identifier,
- procedure_type_expression *heading, block&& body)
- : declaration(position, identifier), m_heading(heading), body(std::make_optional<block>(std::move(body)))
+ procedure_type_expression *heading, procedure_body&& body)
+ : declaration(position, identifier), m_heading(heading),
+ body(std::make_optional<procedure_body>(std::move(body)))
{
}
@@ -538,14 +791,14 @@ namespace elna::boot
}
type_declaration::type_declaration(const struct position position, identifier_definition identifier,
- type_expression *body)
- : declaration(position, identifier), m_body(body)
+ type_expression *underlying_type)
+ : declaration(position, identifier), m_underlying_type(underlying_type)
{
}
type_declaration::~type_declaration()
{
- delete m_body;
+ delete m_underlying_type;
}
void type_declaration::accept(parser_visitor *visitor)
@@ -553,55 +806,56 @@ namespace elna::boot
visitor->visit(this);
}
- type_expression& type_declaration::body()
+ type_expression& type_declaration::underlying_type()
{
- return *m_body;
+ return *m_underlying_type;
}
- block::block(std::vector<constant_declaration *>&& constants, std::vector<variable_declaration *>&& variables,
- std::vector<statement *>&& body)
- : m_variables(std::move(variables)), m_constants(std::move(constants)), m_body(std::move(body))
+ procedure_body::procedure_body(std::vector<constant_declaration *>&& constants,
+ std::vector<variable_declaration *>&& variables, std::vector<statement *>&& statements)
+ : m_variables(std::move(variables)), m_constants(std::move(constants)), m_statements(std::move(statements))
{
}
- block::block(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables)
- : m_variables(std::move(variables)), m_constants(std::move(constants))
+ procedure_body::procedure_body(std::vector<constant_declaration*>&& constants,
+ std::vector<variable_declaration *>&& variables)
+ : procedure_body(std::move(constants), std::move(variables), std::vector<statement *>{})
{
}
- block::block(block&& that)
+ procedure_body::procedure_body(procedure_body&& that)
: m_variables(std::move(that.m_variables)), m_constants(std::move(that.m_constants)),
- m_body(std::move(that.m_body))
+ m_statements(std::move(that.m_statements))
{
}
- block& block::operator=(block&& that)
+ procedure_body& procedure_body::operator=(procedure_body&& that)
{
std::swap(m_variables, that.m_variables);
std::swap(m_constants, that.m_constants);
- std::swap(m_body, that.m_body);
+ std::swap(m_statements, that.m_statements);
return *this;
}
- const std::vector<variable_declaration *>& block::variables()
+ const std::vector<variable_declaration *>& procedure_body::variables()
{
return m_variables;
}
- const std::vector<constant_declaration *>& block::constants()
+ const std::vector<constant_declaration *>& procedure_body::constants()
{
return m_constants;
}
- const std::vector<statement *>& block::body()
+ const std::vector<statement *>& procedure_body::statements()
{
- return m_body;
+ return m_statements;
}
- block::~block()
+ procedure_body::~procedure_body()
{
- for (statement *body_statement : this->body())
+ for (statement *body_statement : this->statements())
{
delete body_statement;
}
@@ -620,8 +874,8 @@ namespace elna::boot
{
}
- unit::unit(const struct position position, std::vector<statement *>&& body)
- : node(position), body(std::make_optional<std::vector<statement *>>(std::move(body)))
+ unit::unit(const struct position position, std::vector<statement *>&& entry_point)
+ : node(position), entry_point(std::make_optional<std::vector<statement *>>(std::move(entry_point)))
{
}
@@ -1073,10 +1327,10 @@ namespace elna::boot
delete m_rvalue;
}
- if_statement::if_statement(const struct position position, conditional_statements *body,
+ if_statement::if_statement(const struct position position, conditional_statements *branch,
std::vector<conditional_statements *>&& branches,
std::vector<statement *> *alternative)
- : node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
+ : node(position), m_branch(branch), branches(std::move(branches)), alternative(alternative)
{
}
@@ -1085,15 +1339,15 @@ namespace elna::boot
visitor->visit(this);
}
- conditional_statements& if_statement::body()
+ conditional_statements& if_statement::branch()
{
- return *m_body;
+ return *m_branch;
}
if_statement::~if_statement()
{
- delete m_body;
- for (const auto branch : branches)
+ delete m_branch;
+ for (conditional_statements *const branch : branches)
{
delete branch;
}
@@ -1110,9 +1364,9 @@ namespace elna::boot
visitor->visit(this);
}
- while_statement::while_statement(const struct position position, conditional_statements *body,
+ while_statement::while_statement(const struct position position, conditional_statements *branch,
std::vector<conditional_statements *>&& branches)
- : node(position), m_body(body), branches(std::move(branches))
+ : node(position), m_branch(branch), branches(std::move(branches))
{
}
@@ -1121,15 +1375,15 @@ namespace elna::boot
visitor->visit(this);
}
- conditional_statements& while_statement::body()
+ conditional_statements& while_statement::branch()
{
- return *m_body;
+ return *m_branch;
}
while_statement::~while_statement()
{
- delete m_body;
- for (const auto branch : branches)
+ delete m_branch;
+ for (conditional_statements *const branch : branches)
{
delete branch;
}
diff --git a/boot/parser.yy b/boot/parser.yy
index 42840ff..6ada702 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -148,7 +148,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::procedure_declaration *>> procedure_part;
%type <elna::boot::type_declaration *> type_declaration;
%type <std::vector<elna::boot::type_declaration *>> type_declarations type_part;
-%type <std::unique_ptr<elna::boot::block>> block;
+%type <std::unique_ptr<elna::boot::procedure_body>> procedure_body;
%type <elna::boot::field_declaration> field_declaration;
%type <std::vector<elna::boot::field_declaration>> optional_fields required_fields;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
@@ -162,32 +162,33 @@ along with GCC; see the file COPYING3. If not see
program:
import_part constant_part type_part variable_part procedure_part statement_part "end" "."
{
+ boot::unit *tree;
if ($6)
{
- boot::unit *tree = new boot::unit(boot::make_position(@1));
- tree->body = std::make_optional<std::vector<boot::statement *>>(std::move(*$6.release()));
-
- driver.tree.reset(tree);
+ tree = new boot::unit(boot::make_position(@1),
+ std::move(*$6.release()));
}
else
{
- driver.tree.reset(new boot::unit(boot::make_position(@1)));
+ tree = new boot::unit(boot::make_position(@1));
}
+ driver.tree.reset(tree);
+
std::swap(driver.tree->imports, $1);
std::swap(driver.tree->constants, $2);
std::swap(driver.tree->types , $3);
std::swap(driver.tree->variables, $4);
std::swap(driver.tree->procedures, $5);
}
-block: constant_part variable_part statement_part "end"
+procedure_body: constant_part variable_part statement_part "end"
{
if ($3)
{
- $$ = std::make_unique<boot::block>(std::move($1), std::move($2), std::move(*$3.release()));
+ $$ = std::make_unique<boot::procedure_body>(std::move($1), std::move($2), std::move(*$3.release()));
}
else
{
- $$ = std::make_unique<boot::block>(std::move($1), std::move($2));
+ $$ = std::make_unique<boot::procedure_body>(std::move($1), std::move($2));
}
}
statement_part:
@@ -221,7 +222,7 @@ procedure_heading: "(" optional_fields ")" return_declaration
$$ = new boot::procedure_type_expression(boot::make_position(@1), std::move($2), std::move($4));
}
procedure_declaration:
- "proc" identifier_definition procedure_heading block
+ "proc" identifier_definition procedure_heading procedure_body
{
$$ = new boot::procedure_declaration(boot::make_position(@1), std::move($2), $3,
std::move(*$4));
@@ -251,7 +252,7 @@ elsif_do_statements:
std::swap($5, $$);
$$.emplace($$.begin(), branch);
}
- | {}
+ | /* no branches */ {}
else_statements:
"else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
| { $$ = nullptr; }
@@ -262,7 +263,7 @@ elsif_then_statements:
std::swap($5, $$);
$$.emplace($$.begin(), branch);
}
- | {}
+ | /* no branches */ {}
return_statement: "return" expression
{ $$ = new boot::return_statement(boot::make_position(@1), $2); }
literal:
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());
}
}
}
diff --git a/boot/symbol.cc b/boot/symbol.cc
index d01eb8e..512cf04 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -429,4 +429,21 @@ namespace elna::boot
{
this->imports.push_front(bag.symbols);
}
+
+ type inner_aliased_type(std::shared_ptr<alias_type> alias)
+ {
+ return inner_aliased_type(alias->reference);
+ }
+
+ type inner_aliased_type(type alias)
+ {
+ if (auto aliased = alias.get<alias_type>())
+ {
+ return inner_aliased_type(aliased);
+ }
+ else
+ {
+ return alias;
+ }
+ }
}