aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-03 00:46:51 +0200
committerEugen Wissner <belka@caraus.de>2026-10-03 00:46:51 +0200
commit128a564be05afb1cb2ec76884a81c2bd536899fd (patch)
tree12bcd5e877aaff326edb253c6b53a3e8b762d699 /boot
parentc8c9cb33f400031a697b4cad7ccc6b8555776e4f (diff)
downloadelna-128a564be05afb1cb2ec76884a81c2bd536899fd.tar.gz
Replace noreturn type with an attribute
Diffstat (limited to 'boot')
-rw-r--r--boot/ast.cc12
-rw-r--r--boot/lexer.ll3
-rw-r--r--boot/name_analysis.cc76
-rw-r--r--boot/parser.yy10
-rw-r--r--boot/symbol.cc23
-rw-r--r--boot/type_check.cc37
6 files changed, 53 insertions, 108 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index 87d6313..bdc9089 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -237,9 +237,9 @@ namespace elna::boot
{
parameter.second->accept(this);
}
- if (declaration->heading().return_type.proper_type != nullptr)
+ if (declaration->heading().return_type != nullptr)
{
- declaration->heading().return_type.proper_type->accept(this);
+ declaration->heading().return_type->accept(this);
}
if (declaration->body.has_value())
{
@@ -394,9 +394,9 @@ namespace elna::boot
{
field.second->accept(this);
}
- if (expression->return_type.proper_type != nullptr)
+ if (expression->return_type != nullptr)
{
- expression->return_type.proper_type->accept(this);
+ expression->return_type->accept(this);
}
}
@@ -949,14 +949,14 @@ namespace elna::boot
}
procedure_type_expression::procedure_type_expression(const source_position position,
- std::vector<field_declaration>&& parameters, return_t return_type)
+ std::vector<field_declaration>&& parameters, type_expression *return_type)
: node(position), return_type(return_type), parameters(std::move(parameters))
{
}
procedure_type_expression::~procedure_type_expression()
{
- delete return_type.proper_type;
+ delete return_type;
}
void procedure_type_expression::accept(parser_visitor *visitor)
diff --git a/boot/lexer.ll b/boot/lexer.ll
index 6fa1904..4452956 100644
--- a/boot/lexer.ll
+++ b/boot/lexer.ll
@@ -476,9 +476,6 @@ module {
@ {
return yy::parser::make_AT(this->location);
}
-! {
- return yy::parser::make_EXCLAMATION(this->location);
-}
-> {
return yy::parser::make_ARROW(this->location);
}
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());
diff --git a/boot/parser.yy b/boot/parser.yy
index cc73aef..04c07a8 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -91,9 +91,7 @@ along with GCC; see the file COPYING3. If not see
%token <bool> BOOLEAN
%token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]"
LEFT_BRACE "{" RIGHT_BRACE "}" GENERIC_OPEN "#[" ATTRIBUTE_OPEN "#{"
-%token ASSIGNMENT ":="
- EXCLAMATION "!" ARROW "->"
- AT "@" HAT "^"
+%token ASSIGNMENT ":=" ARROW "->" AT "@" HAT "^"
COLON ":" SEMICOLON ";" DOT "." COMMA ","
%token PROGRAM "program" MODULE "module"
CAST "cast"
@@ -135,7 +133,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::switch_case>> switch_cases;
%type <elna::boot::variable_declaration *> variable_declaration;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations;
-%type <elna::boot::type_expression *> type_expression;
+%type <elna::boot::type_expression *> type_expression return_declaration;
%type <std::vector<elna::boot::type_expression *>> type_expressions;
%type <elna::boot::expression *> expression operand simple_expression procedure_return unary_expression;
%type <elna::boot::binary_expression *> binary_expression;
@@ -146,7 +144,6 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::statement *>> statements statement_part optional_begin_statements;
%type <elna::boot::procedure_declaration *> procedure_declaration;
%type <elna::boot::procedure_type_expression *> procedure_heading;
-%type <elna::boot::procedure_type_expression::return_t> return_declaration;
%type <elna::boot::type_declaration *> type_declaration;
%type <std::vector<elna::boot::declaration *>> type_declarations sections section;
%type <std::pair<std::vector<elna::boot::import_declaration *>, std::vector<elna::boot::declaration *>>>
@@ -274,8 +271,7 @@ identifier_definitions:
| attributed_identifier { $$.emplace_back(std::move(*$1)); }
return_declaration:
%empty {}
- | "->" "!" { $$ = boot::procedure_type_expression::return_t(std::monostate{}); }
- | "->" type_expression { $$ = boot::procedure_type_expression::return_t($2); }
+ | "->" type_expression { $$ = $2; }
procedure_heading:
"(" field_declarations ")" attributes return_declaration
{
diff --git a/boot/symbol.cc b/boot/symbol.cc
index 54cb595..2293275 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -199,13 +199,9 @@ namespace elna::boot
{
result += " #{varargs}";
}
- if (payload->return_type.no_return)
+ else if (!payload->return_type.empty())
{
- result += " -> !";
- }
- else if (!payload->return_type.proper_type.empty())
- {
- result += " -> " + payload->return_type.proper_type.to_string();
+ result += " -> " + payload->return_type.to_string();
}
return result;
}
@@ -272,7 +268,7 @@ namespace elna::boot
{
}
- procedure_type::procedure_type(return_t return_type)
+ procedure_type::procedure_type(type return_type)
: return_type(std::move(return_type))
{
}
@@ -414,14 +410,14 @@ namespace elna::boot
const type boolean = type(std::make_shared<primitive_type>("Bool", target.bool_properties));
result->enter("Bool", std::make_shared<type_info>(boolean));
- procedure_type assert_symbol{ procedure_type::return_t() };
+ procedure_type assert_symbol{};
assert_symbol.parameters.push_back(boolean);
std::shared_ptr<procedure_info> const assert_info = std::make_shared<procedure_info>(assert_symbol,
std::vector<std::string>{ "condition" });
result->enter("assert", assert_info);
const type load_parameter = type(std::make_shared<parameter_type>("T"));
- procedure_type volatile_load_symbol{ procedure_type::return_t(load_parameter) };
+ procedure_type volatile_load_symbol{ load_parameter };
volatile_load_symbol.parameters.emplace_back(std::make_shared<pointer_type>(load_parameter));
std::shared_ptr<procedure_info> const volatile_load_info =
std::make_shared<procedure_info>(volatile_load_symbol, std::vector<std::string>{ "source" });
@@ -429,7 +425,7 @@ namespace elna::boot
result->enter("volatile_load", volatile_load_info);
const type store_parameter = type(std::make_shared<parameter_type>("T"));
- procedure_type volatile_store_symbol{ procedure_type::return_t() };
+ procedure_type volatile_store_symbol{};
volatile_store_symbol.parameters.emplace_back(std::make_shared<pointer_type>(store_parameter));
volatile_store_symbol.parameters.push_back(store_parameter);
std::shared_ptr<procedure_info> const volatile_store_info =
@@ -626,12 +622,11 @@ namespace elna::boot
}
else if (const auto procedure = subject.get<procedure_type>())
{
- procedure_type::return_t result_return = procedure->return_type;
+ type result_return = procedure->return_type;
- if (!result_return.no_return && !result_return.proper_type.empty())
+ if (!result_return.empty())
{
- result_return = procedure_type::return_t(
- substitute(result_return.proper_type, parameters, arguments));
+ result_return = substitute(result_return, parameters, arguments);
}
const std::shared_ptr<procedure_type> result = std::make_shared<procedure_type>(std::move(result_return));
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 15a01dc..ea0bcd5 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -413,8 +413,8 @@ namespace elna::boot
return opaque;
}
}
- return !procedure->return_type.proper_type.empty()
- ? find_opaque_type(procedure->return_type.proper_type)
+ return !procedure->return_type.empty()
+ ? find_opaque_type(procedure->return_type)
: std::nullopt;
}
return std::nullopt;
@@ -723,18 +723,18 @@ namespace elna::boot
}
++parameter_index;
}
- if (declaration->heading().return_type.proper_type != nullptr)
+ if (declaration->heading().return_type != nullptr)
{
- if (auto opaque = find_opaque_type(this->current_procedure->symbol.return_type.proper_type))
+ if (auto opaque = find_opaque_type(this->current_procedure->symbol.return_type))
{
add_error<type_requirement_error>(
- declaration->heading().return_type.proper_type->position(),
+ declaration->heading().return_type->position(),
opaque.value(), type_requirement_error::kind::opaque_return);
}
- else if (auto found = find_zero_sized(this->current_procedure->symbol.return_type.proper_type, this->target))
+ else if (auto found = find_zero_sized(this->current_procedure->symbol.return_type, this->target))
{
add_error<type_requirement_error>(
- declaration->heading().return_type.proper_type->position(),
+ declaration->heading().return_type->position(),
found.value(), type_requirement_error::kind::zero_sized);
}
}
@@ -750,7 +750,7 @@ namespace elna::boot
void type_analysis_visitor::check_return(const procedure_body& body,
const source_position position, const std::string& name)
{
- const type return_type = this->current_procedure->symbol.return_type.proper_type;
+ const type return_type = this->current_procedure->symbol.return_type;
if (body.return_expression == nullptr)
{
@@ -990,18 +990,17 @@ namespace elna::boot
parameter, type_requirement_error::kind::zero_sized);
}
}
- if (!procedure->return_type.proper_type.empty())
+ if (!procedure->return_type.empty())
{
- if (const auto opaque = find_opaque_type(procedure->return_type.proper_type))
+ if (const auto opaque = find_opaque_type(procedure->return_type))
{
add_error<type_requirement_error>(declaration->position(),
opaque.value(), type_requirement_error::kind::opaque_return);
}
- else if (has_zero_size(procedure->return_type.proper_type, this->target))
+ else if (has_zero_size(procedure->return_type, this->target))
{
add_error<type_requirement_error>(declaration->position(),
- procedure->return_type.proper_type,
- type_requirement_error::kind::zero_sized);
+ procedure->return_type, type_requirement_error::kind::zero_sized);
}
}
}
@@ -1079,8 +1078,8 @@ namespace elna::boot
return true;
}
}
- return !procedure->return_type.proper_type.empty()
- && occurs_in(parameter, procedure->return_type.proper_type);
+ return !procedure->return_type.empty()
+ && occurs_in(parameter, procedure->return_type);
}
else if (const auto instance = subject.get<instantiated_type>())
{
@@ -1206,10 +1205,8 @@ namespace elna::boot
return false;
}
}
- return left_procedure->return_type.proper_type.empty()
- || bind_arguments(parameters, bindings,
- left_procedure->return_type.proper_type,
- right_procedure->return_type.proper_type);
+ return left_procedure->return_type.empty()
+ || bind_arguments(parameters, bindings, left_procedure->return_type, right_procedure->return_type);
}
return true;
}
@@ -1424,7 +1421,7 @@ namespace elna::boot
// just bound.
if (const auto substituted = callable_type.get<procedure_type>())
{
- call->type_decoration = substituted->return_type.proper_type;
+ call->type_decoration = substituted->return_type;
}
}
}