diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/ast.cc | 12 | ||||
| -rw-r--r-- | boot/lexer.ll | 3 | ||||
| -rw-r--r-- | boot/name_analysis.cc | 76 | ||||
| -rw-r--r-- | boot/parser.yy | 10 | ||||
| -rw-r--r-- | boot/symbol.cc | 23 | ||||
| -rw-r--r-- | boot/type_check.cc | 37 |
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; } } } |
