aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/ast.cc93
-rw-r--r--boot/materialization.cc20
-rw-r--r--boot/name_analysis.cc55
-rw-r--r--boot/type_check.cc25
-rw-r--r--boot/validation.cc27
5 files changed, 77 insertions, 143 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index cd2ac55..87d6313 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -243,7 +243,11 @@ namespace elna::boot
}
if (declaration->body.has_value())
{
- traverse_body(this, declaration->body.value());
+ traverse_block(this, declaration->body.value());
+ if (declaration->body.value().return_expression != nullptr)
+ {
+ declaration->body.value().return_expression->accept(this);
+ }
}
}
@@ -253,66 +257,54 @@ namespace elna::boot
statement->rvalue().accept(this);
}
- void walking_visitor::traverse_block(block& body)
- {
- for (variable_declaration *const variable : body.variables)
- {
- variable->accept(this);
- }
- for (statement *const body_statement : body.statements)
- {
- body_statement->accept(this);
- }
- }
-
void walking_visitor::visit(if_statement *statement)
{
statement->branch().prerequisite().accept(this);
- traverse_block(statement->branch().body);
+ traverse_block(this, statement->branch().body);
for (conditional_statements& branch : statement->branches)
{
branch.prerequisite().accept(this);
- traverse_block(branch.body);
+ traverse_block(this, branch.body);
}
if (statement->alternative != nullptr)
{
- traverse_block(*statement->alternative);
+ traverse_block(this, *statement->alternative);
}
}
void walking_visitor::visit(while_statement *statement)
{
statement->branch().prerequisite().accept(this);
- traverse_block(statement->branch().body);
+ traverse_block(this, statement->branch().body);
for (conditional_statements& branch : statement->branches)
{
branch.prerequisite().accept(this);
- traverse_block(branch.body);
+ traverse_block(this, branch.body);
}
}
void walking_visitor::visit(repeat_statement *statement)
{
statement->condition().accept(this);
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
}
void walking_visitor::visit(for_statement *statement)
{
statement->range().accept(this);
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
}
void walking_visitor::visit(defer_statement *statement)
{
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
}
void walking_visitor::visit(block_statement *statement)
{
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
}
void walking_visitor::visit(break_statement *)
@@ -326,50 +318,30 @@ namespace elna::boot
void walking_visitor::visit(case_statement *statement)
{
statement->condition().accept(this);
- for (switch_case& case_block : statement->cases)
+ for (const switch_case& case_block : statement->cases)
{
- for (expression *case_label : case_block.labels)
- {
- case_label->accept(this);
- }
- traverse_block(case_block.body);
+ visit_all(this, case_block.labels);
+ traverse_block(this, case_block.body);
}
if (statement->alternative != nullptr)
{
- traverse_block(*statement->alternative);
+ traverse_block(this, *statement->alternative);
}
}
void walking_visitor::visit(procedure_call *call)
{
call->callable().accept(this);
- for (expression *argument : call->arguments)
- {
- argument->accept(this);
- }
+ visit_all(this, call->arguments);
}
void walking_visitor::visit(unit *unit)
{
- for (import_declaration *_import : unit->imports)
- {
- _import->accept(this);
- }
- for (declaration *const unit_declaration : unit->declarations)
- {
- unit_declaration->accept(this);
- }
+ visit_all(this, unit->imports);
+ visit_all(this, unit->declarations);
if (unit->entry_point.has_value())
{
- visit_entry_point(unit);
- }
- }
-
- void walking_visitor::visit_entry_point(unit *unit)
- {
- for (statement *body_statement : unit->entry_point.value())
- {
- body_statement->accept(this);
+ visit_all(this, unit->entry_point.value());
}
}
@@ -452,10 +424,7 @@ namespace elna::boot
void walking_visitor::visit(array_constructor_expression *expression)
{
- for (auto *element : expression->elements)
- {
- element->accept(this);
- }
+ visit_all(this, expression->elements);
}
void walking_visitor::visit(slicing_expression *expression)
@@ -1115,20 +1084,10 @@ namespace elna::boot
delete this->return_expression;
}
- void traverse_body(parser_visitor *visitor, const procedure_body& body)
+ void traverse_block(parser_visitor *visitor, const block& body)
{
- for (variable_declaration *variable : body.variables)
- {
- variable->accept(visitor);
- }
- for (statement *body_statement : body.statements)
- {
- body_statement->accept(visitor);
- }
- if (body.return_expression != nullptr)
- {
- body.return_expression->accept(visitor);
- }
+ visit_all(visitor, body.variables);
+ visit_all(visitor, body.statements);
}
unit::unit(const source_position position,
diff --git a/boot/materialization.cc b/boot/materialization.cc
index 0ca81aa..6eea0d1 100644
--- a/boot/materialization.cc
+++ b/boot/materialization.cc
@@ -48,6 +48,19 @@ namespace elna::boot
{
}
+ void materialization_visitor::visit(unit *unit)
+ {
+ visit_all(this, unit->imports);
+ visit_all(this, unit->declarations);
+
+ this->in_global_scope = false;
+ if (unit->entry_point.has_value())
+ {
+ visit_all(this, unit->entry_point.value());
+ }
+ this->in_global_scope = true;
+ }
+
void materialization_visitor::visit(procedure_declaration *declaration)
{
this->in_global_scope = false;
@@ -144,11 +157,4 @@ namespace elna::boot
materialization_error::kind::real_overflow);
}
}
-
- void materialization_visitor::visit_entry_point(unit *unit)
- {
- this->in_global_scope = false;
- walking_visitor::visit_entry_point(unit);
- this->in_global_scope = true;
- }
}
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 2ee3da1..20f08ee 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -284,10 +284,7 @@ namespace elna::boot
void forward_declaration_visitor::visit(unit *unit)
{
- for (auto *const unit_declaration: unit->declarations)
- {
- unit_declaration->accept(this);
- }
+ visit_all(this, unit->declarations);
}
void forward_declaration_visitor::visit(type_declaration *declaration)
@@ -733,22 +730,10 @@ namespace elna::boot
statement->rvalue().accept(this);
}
- void resolving_visitor::traverse_block(block& body)
- {
- for (variable_declaration *const variable : body.variables)
- {
- variable->accept(this);
- }
- for (statement *const body_statement : body.statements)
- {
- body_statement->accept(this);
- }
- }
-
void resolving_visitor::visit_block(block& body)
{
body.symbols = this->bag.enter();
- traverse_block(body);
+ traverse_block(this, body);
this->bag.leave();
}
@@ -813,7 +798,7 @@ namespace elna::boot
add_error<symbol_declaration_error>(statement->name.position(),
label_name, original_definition);
}
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
this->bag.leave();
}
@@ -852,10 +837,7 @@ namespace elna::boot
statement->condition().accept(this);
for (switch_case& case_block : statement->cases)
{
- for (expression *case_label : case_block.labels)
- {
- case_label->accept(this);
- }
+ visit_all(this, case_block.labels);
visit_block(case_block.body);
}
if (statement->alternative != nullptr)
@@ -871,10 +853,7 @@ namespace elna::boot
{
call->type_decoration = procedure->return_type.proper_type;
}
- for (expression *const argument : call->arguments)
- {
- argument->accept(this);
- }
+ visit_all(this, call->arguments);
this->current_type = type();
}
@@ -918,11 +897,9 @@ namespace elna::boot
void resolving_visitor::visit(array_constructor_expression *expression)
{
- for (auto *const element : expression->elements)
- {
- element->accept(this);
- }
+ visit_all(this, expression->elements);
const type element_type = expression->elements.front()->type_decoration;
+
expression->type_decoration = type(std::make_shared<array_type>(element_type,
expression->elements.size()));
this->current_type = type();
@@ -1347,10 +1324,7 @@ namespace elna::boot
void declaration_visitor::visit(unit *unit)
{
- for (declaration *const unit_declaration : unit->declarations)
- {
- unit_declaration->accept(this);
- }
+ visit_all(this, unit->declarations);
if (unit->entry_point.has_value())
{
const type word8_primitive = lookup_primitive_type("Word8");
@@ -1540,10 +1514,7 @@ namespace elna::boot
const std::shared_ptr<procedure_info> info = this->bag.lookup("")->is_procedure();
this->bag.enter(info->scope);
- for (statement *body_statement : unit->entry_point.value())
- {
- body_statement->accept(this);
- }
+ visit_all(this, unit->entry_point.value());
this->bag.leave();
}
}
@@ -1590,7 +1561,11 @@ namespace elna::boot
declaration->body->symbols = info->scope;
this->bag.enter(info->scope);
- traverse_body(this, declaration->body.value());
+ traverse_block(this, declaration->body.value());
+ if (declaration->body.value().return_expression != nullptr)
+ {
+ declaration->body.value().return_expression->accept(this);
+ }
this->bag.leave();
}
}
@@ -1612,7 +1587,7 @@ namespace elna::boot
register_variable(statement->counter->name(), lookup_primitive_type("Word"),
statement->counter->position());
}
- traverse_block(statement->body);
+ traverse_block(this, statement->body);
this->bag.leave();
}
}
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 71fd8ab..15a01dc 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -800,13 +800,19 @@ namespace elna::boot
}
}
- void type_analysis_visitor::visit_entry_point(unit *unit)
+ void type_analysis_visitor::visit(unit *unit)
{
- this->current_procedure = this->bag.lookup("")->is_procedure();
- this->bag.enter(this->current_procedure->scope);
- walking_visitor::visit_entry_point(unit);
- this->bag.leave();
- this->current_procedure.reset();
+ visit_all(this, unit->imports);
+ visit_all(this, unit->declarations);
+
+ if (unit->entry_point.has_value())
+ {
+ this->current_procedure = this->bag.lookup("")->is_procedure();
+ this->bag.enter(this->current_procedure->scope);
+ visit_all(this, unit->entry_point.value());
+ this->bag.leave();
+ this->current_procedure.reset();
+ }
}
void type_analysis_visitor::visit(variable_declaration *declaration)
@@ -885,7 +891,7 @@ namespace elna::boot
void type_analysis_visitor::traverse_block(block& body)
{
this->bag.enter(body.symbols);
- walking_visitor::traverse_block(body);
+ boot::traverse_block(this, body);
this->bag.leave();
}
@@ -1409,10 +1415,7 @@ namespace elna::boot
{
// Inference reads the argument types, so they are decorated
// before the parameter types they will be checked against exist.
- for (expression *const argument : call->arguments)
- {
- argument->accept(this);
- }
+ visit_all(this, call->arguments);
inferred = procedure;
callable_type = infer_call(*call, *reference, *procedure);
diff --git a/boot/validation.cc b/boot/validation.cc
index 0c9259e..4539633 100644
--- a/boot/validation.cc
+++ b/boot/validation.cc
@@ -41,34 +41,27 @@ namespace elna::boot
{
}
- void validation_visitor::visit_statements(const std::vector<statement *>& statements)
+ void validation_visitor::visit_statements(const std::vector<statement *>& statements,
+ const std::shared_ptr<symbol_table>& scope)
{
- for (statement *const body_statement : statements)
- {
- body_statement->accept(this);
- }
+ this->bag.enter(scope);
+ visit_all(this, statements);
+ this->bag.leave();
}
void validation_visitor::visit_block(const block& body)
{
- this->bag.enter(body.symbols);
- visit_statements(body.statements);
- this->bag.leave();
+ visit_statements(body.statements, body.symbols);
}
void validation_visitor::visit(unit *unit)
{
- for (declaration *unit_declaration : unit->declarations)
- {
- unit_declaration->accept(this);
- }
+ visit_all(this, unit->declarations);
if (unit->entry_point.has_value())
{
const std::shared_ptr<procedure_info> entry_point = this->bag.lookup("")->is_procedure();
- this->bag.enter(entry_point->scope);
- visit_statements(unit->entry_point.value());
- this->bag.leave();
+ visit_statements(unit->entry_point.value(), entry_point->scope);
}
}
@@ -87,9 +80,7 @@ namespace elna::boot
const std::shared_ptr<procedure_info> procedure =
this->bag.lookup(declaration->identifier.name())->is_procedure();
- this->bag.enter(procedure->scope);
- visit_statements(declaration->body.value().statements);
- this->bag.leave();
+ visit_statements(declaration->body.value().statements, procedure->scope);
}
}