diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-03 00:46:51 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-03 00:46:51 +0200 |
| commit | 128a564be05afb1cb2ec76884a81c2bd536899fd (patch) | |
| tree | 12bcd5e877aaff326edb253c6b53a3e8b762d699 /include | |
| parent | c8c9cb33f400031a697b4cad7ccc6b8555776e4f (diff) | |
| download | elna-128a564be05afb1cb2ec76884a81c2bd536899fd.tar.gz | |
Replace noreturn type with an attribute
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 6 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 87 | ||||
| -rw-r--r-- | include/elna/boot/result.h | 24 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 9 |
4 files changed, 77 insertions, 49 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 8c0ba05..fba8ad4 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -668,15 +668,13 @@ namespace elna::boot class procedure_type_expression : public type_expression { public: - using return_t = return_declaration<type_expression *>; - - const return_t return_type; + type_expression *const return_type; const std::vector<field_declaration> parameters; /// Attributes attached to the procedure type. std::vector<attribute> attributes; procedure_type_expression(const source_position position, - std::vector<field_declaration>&& parameters, return_t return_type = return_t()); + std::vector<field_declaration>&& parameters, type_expression *return_type = nullptr); ~procedure_type_expression() override; void accept(parser_visitor *visitor) override; diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index c726a4f..4e13df1 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -75,7 +75,8 @@ namespace elna::boot enum class attribute_kind { aligned, - varargs + varargs, + noreturn }; /** @@ -93,7 +94,8 @@ namespace elna::boot not_constant, invalid_alignment, unexpected_arguments, - missing_parameter + missing_parameter, + return_type }; attribute_error(const source_position position, const std::string& name, kind attribute_kind); @@ -198,6 +200,26 @@ namespace elna::boot void visit(procedure_declaration *) override; }; + /* + * What the attributes attached to a declaration decide. + */ + struct attribute_values + { + std::optional<std::size_t> alignment; + std::optional<source_position> variadic; + std::optional<source_position> noreturn; + }; + + /** + * Information collected from the procedure declaration. + */ + struct procedure_signature + { + procedure_type heading; + std::vector<std::string> parameter_names; + bool noreturn; + }; + /** * Shared name resolution machinery for the declaration and the body passes. * @@ -217,20 +239,46 @@ namespace elna::boot resolving_visitor(symbol_bag& bag, const target_info& target, const std::filesystem::path& module_path); - procedure_type::return_t build_return_type( - const procedure_type_expression::return_t& return_type); - std::pair<procedure_type, std::vector<std::string>> build_procedure( - procedure_type_expression& expression, bool variadic_supported); + template<attribute_kind... supported> + procedure_signature build_procedure(procedure_type_expression& expression) + { + const type result_return = expression.return_type == nullptr + ? type() + : resolve_type(*expression.return_type); + const attribute_values attributes_result = evaluate_attributes<supported...>(expression.attributes); + procedure_signature result_type{ + .heading = procedure_type(result_return), + .parameter_names = std::vector<std::string>(), + .noreturn = attributes_result.noreturn.has_value() + }; + 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.heading.parameters.push_back(parameter_type); + result_type.parameter_names.push_back(parameter_name.name()); + } + } + if (attributes_result.variadic.has_value() && result_type.heading.parameters.empty()) + { + add_error<attribute_error>(attributes_result.variadic.value(), "varargs", + attribute_error::kind::missing_parameter); + } + if (attributes_result.noreturn.has_value() && expression.return_type != nullptr) + { + add_error<attribute_error>(attributes_result.noreturn.value(), "noreturn", + attribute_error::kind::return_type); + } + result_type.heading.variadic = attributes_result.variadic.has_value(); + + return result_type; + } + ordered_map<field_info> build_composite_type(const std::vector<field_declaration>& fields, ordered_map<field_origin>& field_names, const type& aggregate); - /* - * What the attributes attached to a declaration decide. - */ - struct attribute_values - { - std::optional<std::size_t> alignment; - bool variadic{ false }; - }; static std::optional<attribute_kind> parse_attribute(const std::string& name); /* * Reads the attributes attached to a declaration, reporting the ones @@ -268,13 +316,18 @@ namespace elna::boot { add_error<attribute_error>(position, name, attribute_error::kind::unexpected_arguments); } - else if (result.variadic) + else if ((result.variadic && written_kind.value() == attribute_kind::varargs) + || (result.noreturn && written_kind.value() == attribute_kind::noreturn)) { add_error<attribute_error>(position, name, attribute_error::kind::duplicate); } - else + else if (written_kind.value() == attribute_kind::varargs) + { + result.variadic = std::optional(position); + } + else if (written_kind.value() == attribute_kind::noreturn) { - result.variadic = true; + result.noreturn = std::optional(position); } } return result; diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index d0a550a..c7b79d3 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -161,30 +161,6 @@ namespace elna::boot bool has_errors() const; }; - /** - * Tags a procedure type as never returning. - */ - template<typename T> - struct return_declaration - { - return_declaration() = default; - - explicit return_declaration(T type) - : proper_type(std::move(type)) - { - } - - explicit return_declaration(std::monostate) - : no_return(true) - { - } - - bool operator==(const return_declaration&) const = default; - - T proper_type{}; - bool no_return{ false }; - }; - struct identifier { identifier(const std::string& name, const source_position& position); diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 38aee08..fd56d98 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -197,15 +197,13 @@ namespace elna::boot struct procedure_type { - using return_t = return_declaration<type>; - std::vector<type> parameters; - const return_t return_type; + const type return_type; /// Whether further arguments may follow the parameters, as with a C /// variadic function. bool variadic{ false }; - explicit procedure_type(return_t return_type = return_t()); + explicit procedure_type(type return_type = type()); }; struct enumeration_type @@ -454,6 +452,9 @@ namespace elna::boot /// plain procedure. std::vector<type> parameters; + /// Annotated as a noreturn procedure. + bool noreturn{ false }; + /** * Constructs procedure symbol information. * |
