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.cc183
1 files changed, 108 insertions, 75 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 3c4c6f8..77335d1 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -23,12 +23,12 @@ 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)
+ symbol_declaration_error::symbol_declaration_error(const source_position position, const std::string& name, payload_type payload)
: diagnostic(position), name(name), payload(std::move(payload))
{
}
- std::string declaration_error::what() const
+ std::string symbol_declaration_error::what() const
{
return std::visit([this](const auto& payload) -> std::string {
using T = std::decay_t<decltype(payload)>;
@@ -57,7 +57,7 @@ namespace elna::boot
}, this->payload);
}
- std::optional<diagnostic_note> declaration_error::note() const
+ std::optional<diagnostic_note> symbol_declaration_error::note() const
{
if (std::holds_alternative<redefinition>(this->payload))
{
@@ -89,12 +89,12 @@ namespace elna::boot
return message + " -> " + this->cycle.front();
}
- const_qualifier_error::const_qualifier_error(const source_position position, payload_type payload)
+ declaration_format_error::declaration_format_error(const source_position position, payload_type payload)
: diagnostic(position), payload(std::move(payload))
{
}
- std::string const_qualifier_error::what() const
+ std::string declaration_format_error::what() const
{
return std::visit([](const auto& payload) -> std::string {
using T = std::decay_t<decltype(payload)>;
@@ -112,6 +112,8 @@ namespace elna::boot
return "const must be written before the array size, not after";
case duplicate:
return "Duplicate 'const' qualifier is not allowed";
+ case module_entry:
+ return "Program entry point should have no or one argument";
default:
__builtin_unreachable();
}
@@ -119,7 +121,7 @@ namespace elna::boot
}, this->payload);
}
- std::optional<diagnostic_note> const_qualifier_error::note() const
+ std::optional<diagnostic_note> declaration_format_error::note() const
{
if (std::holds_alternative<not_initialized>(this->payload))
{
@@ -256,9 +258,9 @@ namespace elna::boot
if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second)
{
- add_error<declaration_error>(declaration->identifier.id().position(),
+ add_error<symbol_declaration_error>(declaration->identifier.id().position(),
declaration->identifier.id().name(),
- declaration_error::redefinition{ .original = declaration->position(), .file = {} });
+ symbol_declaration_error::redefinition{ .original = declaration->position(), .file = {} });
}
}
@@ -272,24 +274,28 @@ namespace elna::boot
{
}
- std::pair<procedure_type, std::vector<std::string>> resolving_visitor::build_procedure(
- procedure_type_expression& expression)
+ procedure_type::return_t resolving_visitor::build_return_type(
+ const procedure_type_expression::return_t& return_type)
{
- procedure_type::return_t result_return;
-
- if (expression.return_type.no_return)
+ if (return_type.no_return)
{
- result_return = procedure_type::return_t(std::monostate{});
+ return procedure_type::return_t(std::monostate{});
}
- else if (expression.return_type.proper_type != nullptr)
+ else if (return_type.proper_type != nullptr)
{
- expression.return_type.proper_type->accept(this);
- result_return = procedure_type::return_t(this->current_type);
+ return_type.proper_type->accept(this);
+ return procedure_type::return_t(this->current_type);
}
else
{
- result_return = procedure_type::return_t();
+ return procedure_type::return_t();
}
+ }
+
+ std::pair<procedure_type, std::vector<std::string>> resolving_visitor::build_procedure(
+ procedure_type_expression& expression)
+ {
+ const procedure_type::return_t result_return = build_return_type(expression.return_type);
std::pair<procedure_type, std::vector<std::string>> result_type{
procedure_type(result_return), std::vector<std::string>()
};
@@ -361,9 +367,11 @@ namespace elna::boot
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,
- .file = this->redefinition_file(original) });
+ symbol_declaration_error::redefinition original_definition{
+ .original = original->position,
+ .file = this->redefinition_file(original)
+ };
+ add_error<symbol_declaration_error>(position, name, original_definition);
}
return variable_symbol;
}
@@ -424,8 +432,8 @@ namespace elna::boot
{
auto position_span = source_position(declaration->identifiers.front().id().position().start(),
declaration->identifiers.back().id().position().end());
- add_error<const_qualifier_error>(position_span,
- const_qualifier_error::not_initialized{ extract_identifiers(declaration->identifiers) });
+ add_error<declaration_format_error>(position_span,
+ declaration_format_error::not_initialized{ extract_identifiers(declaration->identifiers) });
}
for (const identifier_definition& variable_identifier : declaration->identifiers)
{
@@ -443,8 +451,8 @@ namespace elna::boot
if (array_base.get<constant_type>() != nullptr)
{
- add_error<const_qualifier_error>(expression->position(),
- const_qualifier_error::kind::array_position);
+ add_error<declaration_format_error>(expression->position(),
+ declaration_format_error::kind::array_position);
}
expression->dimensions().accept(this);
if (expression->dimensions().type_decoration.empty())
@@ -483,8 +491,8 @@ namespace elna::boot
expression->base().accept(this);
if (this->current_type.get<constant_type>() != nullptr)
{
- add_error<const_qualifier_error>(expression->position(),
- const_qualifier_error::kind::duplicate);
+ add_error<declaration_format_error>(expression->position(),
+ declaration_format_error::kind::duplicate);
}
this->current_type = type(std::make_shared<constant_type>(this->current_type));
}
@@ -512,8 +520,8 @@ namespace elna::boot
}
else
{
- add_error<declaration_error>(expression->base.value().position(),
- expression->base.value().name(), declaration_error::kind::undeclared_type);
+ add_error<symbol_declaration_error>(expression->base.value().position(),
+ expression->base.value().name(), symbol_declaration_error::kind::undeclared_type);
this->current_type = type();
return;
}
@@ -698,8 +706,8 @@ namespace elna::boot
}
else
{
- add_error<declaration_error>(expression->type_name.position(),
- expression->type_name.name(), declaration_error::kind::undeclared_type);
+ add_error<symbol_declaration_error>(expression->type_name.position(),
+ expression->type_name.name(), symbol_declaration_error::kind::undeclared_type);
}
for (const field_initializer& initializer : expression->field_initializers)
{
@@ -766,8 +774,8 @@ namespace elna::boot
}
else
{
- add_error<declaration_error>(trait->name.position(),
- trait->name.name(), declaration_error::kind::undeclared_trait);
+ add_error<symbol_declaration_error>(trait->name.position(),
+ trait->name.name(), symbol_declaration_error::kind::undeclared_trait);
}
this->current_type = type();
}
@@ -847,8 +855,8 @@ namespace elna::boot
}
else
{
- add_error<declaration_error>(expression->position(),
- expression->name, declaration_error::kind::undeclared_symbol);
+ add_error<symbol_declaration_error>(expression->position(),
+ expression->name, symbol_declaration_error::kind::undeclared_symbol);
}
}
@@ -1112,6 +1120,49 @@ namespace elna::boot
{
procedure->accept(this);
}
+ if (unit->entry_point.has_value())
+ {
+ auto word8_primitive = lookup_primitive_type("Word8");
+ const procedure_type::return_t result_return = procedure_type::return_t(word8_primitive);
+ auto heading = procedure_type(result_return);
+ std::shared_ptr<procedure_info> info;
+
+ if (unit->parameters.size() > 1)
+ {
+ add_error<declaration_format_error>(unit->position(),
+ declaration_format_error::kind::module_entry);
+ }
+ else if (unit->parameters.size() == 1)
+ {
+ auto variable_type = type(std::make_shared<pointer_type>(word8_primitive));
+ variable_type = type(std::make_shared<slice_type>(variable_type));
+
+ heading.parameters.push_back(variable_type);
+
+ info = std::make_shared<procedure_info>(heading,
+ std::vector<std::string>({ unit->parameters.at(0).name() }), this->bag.enter());
+
+ register_variable(info->names.at(0), variable_type, unit->parameters.at(0).position());
+ }
+ else
+ {
+ info = std::make_shared<procedure_info>(heading, std::vector<std::string>{}, this->bag.enter());
+ }
+ this->bag.leave();
+
+ info->position.emplace(unit->position());
+ info->file = this->module_file;
+
+ if (!this->bag.enter("", info))
+ {
+ auto original = this->bag.lookup("");
+ symbol_declaration_error::redefinition original_definition{
+ .original = original->position,
+ .file = this->redefinition_file(original)
+ };
+ add_error<symbol_declaration_error>(unit->position(), "program", original_definition);
+ }
+ }
}
void declaration_visitor::visit(type_declaration *declaration)
@@ -1138,9 +1189,12 @@ namespace elna::boot
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) });
+ symbol_declaration_error::redefinition original_definition{
+ .original = original->position,
+ .file = this->redefinition_file(original)
+ };
+ add_error<symbol_declaration_error>(declaration->identifier.id().position(),
+ declaration->identifier.name(), original_definition);
}
}
@@ -1159,7 +1213,6 @@ namespace elna::boot
{
auto variable_symbol = register_variable(*name_iterator, *type_iterator,
declaration->heading().position());
- variable_symbol->exported = false;
++name_iterator;
++type_iterator;
@@ -1176,9 +1229,12 @@ namespace elna::boot
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) });
+ symbol_declaration_error::redefinition original_definition{
+ .original = original->position,
+ .file = this->redefinition_file(original)
+ };
+ add_error<symbol_declaration_error>(declaration->identifier.id().position(),
+ declaration->identifier.name(), original_definition);
}
}
@@ -1199,25 +1255,12 @@ namespace elna::boot
{
procedure->accept(this);
}
- if (unit->has_body())
+ if (unit->entry_point.has_value())
{
- this->bag.enter();
- auto variable_type = lookup_primitive_type("Int");
- 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));
- auto parameters_symbol = std::make_shared<variable_info>(variable_type, false);
- parameters_symbol->file = this->module_file;
- this->bag.enter("parameters", parameters_symbol);
+ const std::shared_ptr<procedure_info> info = this->bag.lookup("")->is_procedure();
- for (statement *const statement : unit->entry_point)
- {
- statement->accept(this);
- }
+ this->bag.enter(info->scope);
+ traverse_body(this, unit->entry_point.value());
this->bag.leave();
}
}
@@ -1234,31 +1277,21 @@ namespace elna::boot
{
if (variable_identifier.exported())
{
- add_error<declaration_error>(variable_identifier.id().position(),
- variable_identifier.id().name(), declaration_error::kind::local_export);
+ add_error<symbol_declaration_error>(variable_identifier.id().position(),
+ variable_identifier.id().name(), symbol_declaration_error::kind::local_export);
}
}
}
void name_analysis_visitor::visit(procedure_declaration *declaration)
{
- const std::shared_ptr<procedure_info> info = this->bag.lookup(declaration->identifier.name())->is_procedure();
-
if (declaration->body.has_value())
{
+ const std::shared_ptr<procedure_info> info =
+ this->bag.lookup(declaration->identifier.name())->is_procedure();
+
this->bag.enter(info->scope);
- for (variable_declaration *const variable : declaration->body.value().variables)
- {
- variable->accept(this);
- }
- for (statement *const statement : declaration->body.value().entry_point)
- {
- statement->accept(this);
- }
- if (declaration->body.value().return_expression != nullptr)
- {
- declaration->body.value().return_expression->accept(this);
- }
+ traverse_body(this, declaration->body.value());
this->bag.leave();
}
}