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.cc76
1 files changed, 18 insertions, 58 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 20f08ee..1a87927 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -90,6 +90,8 @@ namespace elna::boot
return "Attribute '" + this->name + "' takes no arguments";
case missing_parameter:
return "Attribute '" + this->name + "' requires at least one parameter";
+ case return_type:
+ return "Attribute '" + this->name + "' cannot be used with a return type";
default:
__builtin_unreachable();
}
@@ -317,53 +319,6 @@ namespace elna::boot
{
}
- procedure_type::return_t resolving_visitor::build_return_type(
- const procedure_type_expression::return_t& return_type)
- {
- if (return_type.no_return)
- {
- return procedure_type::return_t(std::monostate{});
- }
- else if (return_type.proper_type != nullptr)
- {
- return procedure_type::return_t(resolve_type(*return_type.proper_type));
- }
- else
- {
- return procedure_type::return_t();
- }
- }
-
- std::pair<procedure_type, std::vector<std::string>> resolving_visitor::build_procedure(
- procedure_type_expression& expression, const bool variadic_supported)
- {
- 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>()
- };
- for (const auto& [parameter_names, parameters_type] : expression.parameters)
- {
- const type parameter_type = resolve_type(*parameters_type);
-
- for (const auto& parameter_name : parameter_names)
- {
- evaluate_attributes<>(parameter_name.attributes);
- result_type.first.parameters.push_back(parameter_type);
- result_type.second.push_back(parameter_name.name());
- }
- }
- result_type.first.variadic = variadic_supported
- ? evaluate_attributes<attribute_kind::varargs>(expression.attributes).variadic
- : evaluate_attributes<>(expression.attributes).variadic;
-
- if (result_type.first.variadic && result_type.first.parameters.empty())
- {
- add_error<attribute_error>(expression.position(), "varargs",
- attribute_error::kind::missing_parameter);
- }
- return result_type;
- }
-
std::optional<attribute_kind> resolving_visitor::parse_attribute(const std::string& name)
{
if (name == "aligned")
@@ -374,6 +329,10 @@ namespace elna::boot
{
return attribute_kind::varargs;
}
+ if (name == "noreturn")
+ {
+ return attribute_kind::noreturn;
+ }
return std::nullopt;
}
@@ -676,16 +635,15 @@ namespace elna::boot
ordered_map<field_origin> field_names;
collect_field_names(result_type->base, field_names);
result_type->fields = build_composite_type(expression->fields, field_names, type(result_type));
- result_type->alignment =
- evaluate_attributes<attribute_kind::aligned>(expression->attributes).alignment;
+ result_type->alignment = evaluate_attributes<attribute_kind::aligned>(expression->attributes).alignment;
this->current_type = type(result_type);
}
void resolving_visitor::visit(procedure_type_expression *expression)
{
- std::shared_ptr<procedure_type> const result_type =
- std::make_shared<procedure_type>(std::move(build_procedure(*expression, true).first));
+ const std::shared_ptr<procedure_type> result_type =
+ std::make_shared<procedure_type>(build_procedure<attribute_kind::varargs>(*expression).heading);
this->current_type = type(result_type);
}
@@ -851,7 +809,7 @@ namespace elna::boot
call->callable().accept(this);
if (const auto procedure = call->callable().type_decoration.get<procedure_type>())
{
- call->type_decoration = procedure->return_type.proper_type;
+ call->type_decoration = procedure->return_type;
}
visit_all(this, call->arguments);
this->current_type = type();
@@ -1290,10 +1248,10 @@ namespace elna::boot
return false;
}
}
- if (!link->return_type.proper_type.empty())
+ if (!link->return_type.empty())
{
alias_path.resize(saved_path);
- return find_alias_cycle(being_resolved, link->return_type.proper_type, alias_path, state);
+ return find_alias_cycle(being_resolved, link->return_type, alias_path, state);
}
return true;
}
@@ -1328,8 +1286,7 @@ namespace elna::boot
if (unit->entry_point.has_value())
{
const type 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);
+ auto heading = procedure_type(word8_primitive);
std::shared_ptr<procedure_info> info;
if (unit->parameters.size() > 1)
@@ -1451,8 +1408,9 @@ namespace elna::boot
// is why the body sees them too.
const std::shared_ptr<symbol_table> scope = this->bag.enter();
const std::vector<type> type_parameters = enter_parameters(declaration->parameters);
- auto [heading, parameter_names] =
- build_procedure(declaration->heading(), !declaration->body.has_value());
+ auto [heading, parameter_names, noreturn] = !declaration->body.has_value()
+ ? build_procedure<attribute_kind::varargs, attribute_kind::noreturn>(declaration->heading())
+ : build_procedure<attribute_kind::noreturn>(declaration->heading());
std::shared_ptr<procedure_info> info_object;
if (declaration->body.has_value())
@@ -1480,6 +1438,8 @@ namespace elna::boot
info_object->exported = declaration->identifier.exported();
info_object->position.emplace(declaration->position());
info_object->file = this->module_file;
+ info_object->noreturn = noreturn;
+
if (!this->bag.enter(declaration->identifier.name(), info_object))
{
const std::shared_ptr<info> original = this->bag.lookup(declaration->identifier.name());