aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h6
-rw-r--r--include/elna/boot/name_analysis.h87
-rw-r--r--include/elna/boot/result.h24
-rw-r--r--include/elna/boot/symbol.h9
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.
*