aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/evaluator.cc50
-rw-r--r--boot/name_analysis.cc65
-rw-r--r--boot/result.cc22
-rw-r--r--boot/type_check.cc184
-rw-r--r--boot/validation.cc25
-rw-r--r--include/elna/boot/name_analysis.h4
-rw-r--r--include/elna/boot/result.h13
-rw-r--r--include/elna/boot/type_check.h58
-rw-r--r--include/elna/boot/validation.h10
9 files changed, 239 insertions, 192 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index d8d9ddc..07b2953 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -53,20 +53,14 @@ namespace elna::boot
std::optional<std::pair<std::string, source_position>> non_constant_expression_error::note() const
{
- return std::visit([](const auto& payload) -> std::optional<std::pair<std::string, source_position>> {
- using T = std::decay_t<decltype(payload)>;
-
- if constexpr (std::is_same_v<T, initializer>)
- {
- auto position_span = source_position(payload.identifiers.front().position().start(),
- payload.identifiers.back().position().end());
- return std::make_pair(join(payload.identifiers), position_span);
- }
- else
- {
- return std::nullopt;
- }
- }, this->payload);
+ if (std::holds_alternative<initializer>(this->payload))
+ {
+ return identifier_list_note(std::get<initializer>(this->payload).identifiers);
+ }
+ else
+ {
+ return std::nullopt;
+ }
}
std::optional<type_properties> get_type_properties(const type& subject, const target_info& target)
@@ -239,33 +233,29 @@ namespace elna::boot
std::optional<constant_value> evaluator::evaluate_literal(literal_expression& subject)
{
- // The type decoration here is trustable since the name analysis derives
- // the decoration from literal's own value.
- type const decoration = subject.type_decoration;
-
- if (is_primitive_type(decoration, "Int") || is_primitive_type(decoration, "Word"))
+ if (auto *integer_subject = subject.is_a<integer_literal>())
{
- return constant_value{ static_cast<literal<integer_literal>&>(subject).value };
+ return constant_value{ integer_subject->value };
}
- else if (is_primitive_type(decoration, "Float"))
+ else if (auto *double_subject = subject.is_a<double>())
{
- return constant_value{ static_cast<literal<double>&>(subject).value };
+ return constant_value{ double_subject->value };
}
- else if (is_primitive_type(decoration, "Bool"))
+ else if (auto *boolean_subject = subject.is_a<bool>())
{
- return constant_value{ static_cast<literal<bool>&>(subject).value };
+ return constant_value{ boolean_subject->value };
}
- else if (is_primitive_type(decoration, "Char"))
+ else if (auto *character_subject = subject.is_a<unsigned char>())
{
- return constant_value{ static_cast<literal<unsigned char>&>(subject).value };
+ return constant_value{ character_subject->value };
}
- else if (is_primitive_type(decoration, "Pointer"))
+ else if (auto *pointer_subject = subject.is_a<std::nullptr_t>())
{
- return constant_value{ std::nullptr_t{} };
+ return constant_value{ pointer_subject->value };
}
- else if (is_string_type(decoration))
+ else if (auto *string_subject = subject.is_a<std::string>())
{
- return constant_value{ static_cast<literal<std::string>&>(subject).value };
+ return constant_value{ string_subject->value };
}
return std::nullopt;
}
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index ae6810d..4127466 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -59,22 +59,22 @@ namespace elna::boot
std::optional<std::pair<std::string, source_position>> declaration_error::note() const
{
- if (const auto *redef = std::get_if<redefinition>(&payload))
+ if (std::holds_alternative<redefinition>(this->payload))
{
- if (redef->original.has_value() && redef->original->start().available())
- {
- return std::make_pair("previously declared here", *redef->original);
- }
+ return previous_declaration_note(std::get<redefinition>(this->payload).original);
+ }
+ else
+ {
+ return std::nullopt;
}
- return std::nullopt;
}
- name_analysis_error::name_analysis_error(const source_position position, payload_type payload)
+ const_qualifier_error::const_qualifier_error(const source_position position, payload_type payload)
: error(position), payload(std::move(payload))
{
}
- std::string name_analysis_error::what() const
+ std::string const_qualifier_error::what() const
{
return std::visit([](const auto& payload) -> std::string {
using T = std::decay_t<decltype(payload)>;
@@ -99,23 +99,16 @@ namespace elna::boot
}, this->payload);
}
- std::optional<std::pair<std::string, source_position>> name_analysis_error::note() const
+ std::optional<std::pair<std::string, source_position>> const_qualifier_error::note() const
{
- return std::visit([](const auto& payload) -> std::optional<std::pair<std::string, source_position>> {
- using T = std::decay_t<decltype(payload)>;
-
- if constexpr (std::is_same_v<T, not_initialized>)
- {
- auto position_span = source_position(payload.identifiers.front().position().start(),
- payload.identifiers.back().position().end());
-
- return std::make_optional(std::make_pair(join(payload.identifiers), position_span));
- }
- else
- {
- return std::nullopt;
- }
- }, this->payload);
+ if (std::holds_alternative<not_initialized>(this->payload))
+ {
+ return identifier_list_note(std::get<not_initialized>(this->payload).identifiers);
+ }
+ else
+ {
+ return std::nullopt;
+ }
}
member_error::member_error(const source_position position, const std::string& name,
@@ -184,14 +177,14 @@ namespace elna::boot
std::optional<std::pair<std::string, source_position>> member_error::note() const
{
- if (const auto *dup = std::get_if<duplicate>(&payload))
+ if (std::holds_alternative<duplicate>(this->payload))
{
- if (dup->original.has_value() && dup->original->start().available())
- {
- return std::make_pair("previously declared here", *dup->original);
- }
+ return previous_declaration_note(std::get<duplicate>(this->payload).original);
+ }
+ else
+ {
+ return std::nullopt;
}
- return std::nullopt;
}
// Members of a constant aggregate are constant themselves.
@@ -317,8 +310,8 @@ namespace elna::boot
if (this->current_type.get<constant_type>() != nullptr)
{
- add_error<name_analysis_error>(expression->position(),
- name_analysis_error::kind::duplicate);
+ add_error<const_qualifier_error>(expression->position(),
+ const_qualifier_error::kind::duplicate);
}
this->current_type = type(std::make_shared<constant_type>(this->current_type));
}
@@ -330,8 +323,8 @@ namespace elna::boot
if (array_base.get<constant_type>() != nullptr)
{
- add_error<name_analysis_error>(expression->position(),
- name_analysis_error::kind::array_position);
+ add_error<const_qualifier_error>(expression->position(),
+ const_qualifier_error::kind::array_position);
}
expression->dimensions().accept(this);
const auto size_constant = this->constant_evaluator.evaluate_index(expression->dimensions());
@@ -580,8 +573,8 @@ namespace elna::boot
{
auto position_span = source_position(declaration->identifiers.front().id().position().start(),
declaration->identifiers.back().id().position().end());
- add_error<name_analysis_error>(position_span,
- name_analysis_error::not_initialized{ extract_identifiers(declaration->identifiers) });
+ add_error<const_qualifier_error>(position_span,
+ const_qualifier_error::not_initialized{ extract_identifiers(declaration->identifiers) });
}
for (const identifier_definition& variable_identifier : declaration->identifiers)
{
diff --git a/boot/result.cc b/boot/result.cc
index 15fe8b4..a5f0803 100644
--- a/boot/result.cc
+++ b/boot/result.cc
@@ -129,6 +129,28 @@ namespace elna::boot
return this->m_exported;
}
+ std::optional<std::pair<std::string, source_position>> previous_declaration_note(
+ const std::optional<source_position>& original, std::string_view label)
+ {
+ if (original.has_value() && original.value().start().available())
+ {
+ return std::make_pair(std::string(label), original.value());
+ }
+ else
+ {
+ return std::nullopt;
+ }
+ }
+
+ std::optional<std::pair<std::string, source_position>> identifier_list_note(
+ const std::vector<identifier>& identifiers)
+ {
+ auto position_span = source_position(identifiers.front().position().start(),
+ identifiers.back().position().end());
+
+ return std::make_optional(std::make_pair(join(identifiers), position_span));
+ }
+
std::vector<identifier> extract_identifiers(const std::vector<identifier_definition>& identifiers)
{
std::vector<identifier> result;
diff --git a/boot/type_check.cc b/boot/type_check.cc
index b1739d9..07e563f 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -100,14 +100,7 @@ namespace elna::boot
{
using T = std::decay_t<decltype(payload)>;
- if constexpr (std::is_same_v<T, argument_count>)
- {
- return "Trait #" + this->trait_name + " expects "
- + std::to_string(payload.expected) + " argument"
- + (payload.expected != 1 ? "s" : "") + ", got "
- + std::to_string(payload.actual);
- }
- else if constexpr (std::is_same_v<T, offset_not_field_name>)
+ if constexpr (std::is_same_v<T, offset_not_field_name>)
{
return "The second argument to the #" + this->trait_name
+ " trait must be a field name";
@@ -170,41 +163,50 @@ namespace elna::boot
return "The number " + payload.overflow.to_string()
+ " does not fit into the type '" + actual.to_string() + "'";
}
- else if constexpr (std::is_same_v<T, kind>)
+ else if constexpr (std::is_same_v<T, constant_assignment>)
{
- switch (payload)
- {
- using enum kind;
- case record_base:
- return "Expected a record type, but got '"
- + this->actual.to_string() + "'";
- case for_range:
- return "Expected an array or slice type, but got '"
- + this->actual.to_string() + "'";
- case condition:
- return "Condition must be a boolean expression, but got '"
- + this->actual.to_string() + "'";
- case constant_assignment:
- return "Cannot assign to a value of type '" + this->actual.to_string()
- + "', because it is constant or contains constant members";
- case array_index:
- return "Array index must be an integral type, but got '"
- + this->actual.to_string() + "'";
- case non_indexable:
- return "Indexing is not allowed on type '"
- + this->actual.to_string() + "'";
- case dereference_of_non_pointer:
- return "Type '" + this->actual.to_string()
- + "' cannot be dereferenced, it is not a pointer";
- default:
- __builtin_unreachable();
- }
+ return "Cannot assign to a value of type '" + this->actual.to_string()
+ + "', because it is constant or contains constant members";
}
}, this->payload);
}
- cyclic_declaration_error::cyclic_declaration_error(const std::vector<std::string>& cycle,
- const source_position position)
+ type_requirement_error::type_requirement_error(const source_position position,
+ type actual, kind kind)
+ : error(position), actual(std::move(actual)), m_kind(kind)
+ {
+ }
+
+ std::string type_requirement_error::what() const
+ {
+ switch (this->m_kind)
+ {
+ using enum kind;
+ case record_base:
+ return "Expected a record type, but got '"
+ + this->actual.to_string() + "'";
+ case for_range:
+ return "Expected an array or slice type, but got '"
+ + this->actual.to_string() + "'";
+ case condition:
+ return "Condition must be a boolean expression, but got '"
+ + this->actual.to_string() + "'";
+ case array_index:
+ return "Array index must be an integral type, but got '"
+ + this->actual.to_string() + "'";
+ case non_indexable:
+ return "Indexing is not allowed on type '"
+ + this->actual.to_string() + "'";
+ case dereference_of_non_pointer:
+ return "Type '" + this->actual.to_string()
+ + "' cannot be dereferenced, it is not a pointer";
+ default:
+ __builtin_unreachable();
+ }
+ }
+
+ cyclic_declaration_error::cyclic_declaration_error(const source_position position,
+ const std::vector<std::string>& cycle)
: error(position), cycle(cycle)
{
}
@@ -222,24 +224,35 @@ namespace elna::boot
return message;
}
- argument_count_error::argument_count_error(std::size_t expected, std::size_t actual,
- const source_position position)
- : error(position), expected(expected), actual(actual)
+ argument_count_error::argument_count_error(const source_position position, kind kind,
+ std::string applicand, std::size_t expected, std::size_t actual)
+ : error(position), m_kind(kind), applicand(std::move(applicand)), expected(expected), actual(actual)
{
}
std::string argument_count_error::what() const
{
- if (actual > expected)
+ std::string entity;
+
+ switch (this->m_kind)
{
- return "Too many arguments, expected " + std::to_string(expected)
- + ", got " + std::to_string(actual);
+ using enum kind;
+ case trait:
+ entity = '#' + this->applicand;
+ break;
+ case call:
+ entity = '\'' + this->applicand + '\'';
+ break;
+ case array:
+ entity = "array initializer '" + this->applicand + "'";
+ break;
}
- else
- {
- return "Too few arguments, expected " + std::to_string(expected)
+ const std::string noun = this->m_kind == kind::array ? "elements" : "arguments";
+ const std::string quantifier = actual > expected ? "many" : "few";
+
+ return "Too " + quantifier + " " + noun + " for " + entity
+ + ", expected " + std::to_string(expected)
+ ", got " + std::to_string(actual);
- }
}
static bool contains_constant_member(const type& checked)
@@ -302,8 +315,8 @@ namespace elna::boot
condition.accept(this);
if (!is_primitive_type(condition.type_decoration, "Bool"))
{
- add_error<type_mismatch_error>(condition.position(),
- condition.type_decoration, type_mismatch_error::kind::condition);
+ add_error<type_requirement_error>(condition.position(),
+ condition.type_decoration, type_requirement_error::kind::condition);
}
}
@@ -516,7 +529,7 @@ namespace elna::boot
if (contains_constant_member(statement->lvalue().type_decoration))
{
add_error<type_mismatch_error>(statement->position(), statement->lvalue().type_decoration,
- type_mismatch_error::kind::constant_assignment);
+ type_mismatch_error::constant_assignment{});
}
else if (!is_assignable_from(statement->lvalue().type_decoration, statement->rvalue().type_decoration))
{
@@ -574,8 +587,8 @@ namespace elna::boot
if (!get_range_base_type(resolved_range))
{
- add_error<type_mismatch_error>(statement->range().position(),
- statement->range().type_decoration, type_mismatch_error::kind::for_range);
+ add_error<type_requirement_error>(statement->range().position(),
+ statement->range().type_decoration, type_requirement_error::kind::for_range);
}
this->bag.enter(statement->symbols);
for (auto *body_statement : statement->body)
@@ -647,7 +660,7 @@ namespace elna::boot
if (!check_unresolved_symbol(unresolved_type, alias_path))
{
- add_error<cyclic_declaration_error>(alias_path, declaration->position());
+ add_error<cyclic_declaration_error>(declaration->position(), alias_path);
}
else
{
@@ -662,16 +675,16 @@ namespace elna::boot
auto const base_symbol = this->bag.lookup(expression->base.value().name());
if (base_symbol == nullptr || base_symbol->is_type() == nullptr)
{
- add_error<type_mismatch_error>(expression->position(),
- type(), type_mismatch_error::kind::record_base);
+ add_error<type_requirement_error>(expression->position(),
+ type(), type_requirement_error::kind::record_base);
}
else
{
type const base_type = resolve_underlying_type(base_symbol->is_type()->symbol);
if (base_type.get<record_type>() == nullptr)
{
- add_error<type_mismatch_error>(expression->position(),
- base_type, type_mismatch_error::kind::record_base);
+ add_error<type_requirement_error>(expression->position(),
+ base_type, type_requirement_error::kind::record_base);
}
}
}
@@ -703,8 +716,18 @@ namespace elna::boot
}
if (call->arguments.size() != procedure->parameters.size())
{
- add_error<argument_count_error>(procedure->parameters.size(),
- call->arguments.size(), call->position());
+ if (auto *procedure_name = call->callable().is_named())
+ {
+ add_error<argument_count_error>(call->position(),
+ argument_count_error::kind::call, procedure_name->name,
+ procedure->parameters.size(), call->arguments.size());
+ }
+ else
+ {
+ add_error<argument_count_error>(call->position(),
+ argument_count_error::kind::call, call->callable().type_decoration.to_string(),
+ procedure->parameters.size(), call->arguments.size());
+ }
}
}
else if (!call->callable().type_decoration.empty())
@@ -757,8 +780,9 @@ namespace elna::boot
}
if (expression->elements.size() > array->size)
{
- add_error<argument_count_error>(array->size, expression->elements.size(),
- expression->position());
+ add_error<argument_count_error>(expression->position(),
+ argument_count_error::kind::array, expression->type_decoration.to_string(),
+ array->size, expression->elements.size());
return;
}
for (auto *element : expression->elements)
@@ -778,13 +802,13 @@ namespace elna::boot
if (!is_integral_type(resolve_underlying_type(expression->start().type_decoration)))
{
- add_error<type_mismatch_error>(expression->start().position(),
- expression->start().type_decoration, type_mismatch_error::kind::array_index);
+ add_error<type_requirement_error>(expression->start().position(),
+ expression->start().type_decoration, type_requirement_error::kind::array_index);
}
if (!is_integral_type(resolve_underlying_type(expression->end().type_decoration)))
{
- add_error<type_mismatch_error>(expression->end().position(),
- expression->end().type_decoration, type_mismatch_error::kind::array_index);
+ add_error<type_requirement_error>(expression->end().position(),
+ expression->end().type_decoration, type_requirement_error::kind::array_index);
}
}
@@ -796,13 +820,13 @@ namespace elna::boot
if (resolved_base.get<array_type>() == nullptr
&& resolved_base.get<slice_type>() == nullptr)
{
- add_error<type_mismatch_error>(expression->position(),
- expression->base().type_decoration, type_mismatch_error::kind::non_indexable);
+ add_error<type_requirement_error>(expression->position(),
+ expression->base().type_decoration, type_requirement_error::kind::non_indexable);
}
if (!is_integral_type(resolve_underlying_type(expression->index().type_decoration)))
{
- add_error<type_mismatch_error>(expression->index().position(),
- expression->index().type_decoration, type_mismatch_error::kind::array_index);
+ add_error<type_requirement_error>(expression->index().position(),
+ expression->index().type_decoration, type_requirement_error::kind::array_index);
}
}
@@ -867,9 +891,8 @@ namespace elna::boot
if (resolve_underlying_type(expression->base().type_decoration).get<pointer_type>() == nullptr)
{
- add_error<type_mismatch_error>(expression->position(),
- expression->base().type_decoration,
- type_mismatch_error::kind::dereference_of_non_pointer);
+ add_error<type_requirement_error>(expression->position(), expression->base().type_decoration,
+ type_requirement_error::kind::dereference_of_non_pointer);
}
}
@@ -994,16 +1017,18 @@ namespace elna::boot
{
if (trait->arguments.size() != 1)
{
- add_error<trait_error>(trait->position(), trait->name.name(),
- trait_error::argument_count{ .expected = 1, .actual = trait->arguments.size() });
+ add_error<argument_count_error>(trait->position(),
+ argument_count_error::kind::trait, trait->name.name(),
+ 1, trait->arguments.size());
}
}
else if ((trait->name == "min" || trait->name == "max") && !trait->type_decoration.empty())
{
if (trait->arguments.size() != 1)
{
- add_error<trait_error>(trait->position(), trait->name.name(),
- trait_error::argument_count{ .expected = 1, .actual = trait->arguments.size() });
+ add_error<argument_count_error>(trait->position(),
+ argument_count_error::kind::trait, trait->name.name(),
+ 1, trait->arguments.size());
}
else
{
@@ -1022,8 +1047,9 @@ namespace elna::boot
{
if (trait->arguments.size() != 2)
{
- add_error<trait_error>(trait->position(), trait->name.name(),
- trait_error::argument_count{ .expected = 2, .actual = trait->arguments.size() });
+ add_error<argument_count_error>(trait->position(),
+ argument_count_error::kind::trait, trait->name.name(),
+ 2, trait->arguments.size());
}
else if (trait->arguments.at(1)->is_named() == nullptr)
{
diff --git a/boot/validation.cc b/boot/validation.cc
index 0c03fd0..26d4f64 100644
--- a/boot/validation.cc
+++ b/boot/validation.cc
@@ -21,33 +21,19 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
- validation_error::validation_error(const source_position position, payload_type payload)
- : error(position), payload(payload)
+ validation_error::validation_error(const source_position position, source_position first)
+ : error(position), first(first)
{
}
std::string validation_error::what() const
{
- return std::visit([](const auto& payload) -> std::string {
- using T = std::decay_t<decltype(payload)>;
-
- if constexpr (std::is_same_v<T, duplicate_case>)
- {
- return "Duplicate case label";
- }
- }, this->payload);
+ return "Duplicate case label";
}
std::optional<std::pair<std::string, source_position>> validation_error::note() const
{
- return std::visit([](const auto& payload) -> std::optional<std::pair<std::string, source_position>> {
- using T = std::decay_t<decltype(payload)>;
-
- if constexpr (std::is_same_v<T, duplicate_case>)
- {
- return std::make_pair("Previous label here", payload.first);
- }
- }, this->payload);
+ return previous_declaration_note(this->first, "Previous label here");
}
validation_visitor::validation_visitor(symbol_bag& bag, const target_info& target)
@@ -145,8 +131,7 @@ namespace elna::boot
auto [case_position, inserted] = seen.try_emplace(value.value(), label->position());
if (!inserted)
{
- add_error<validation_error>(label->position(),
- validation_error::duplicate_case{ case_position->second });
+ add_error<validation_error>(label->position(), case_position->second);
}
}
}
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h
index 9e10fab..a9e7f24 100644
--- a/include/elna/boot/name_analysis.h
+++ b/include/elna/boot/name_analysis.h
@@ -63,7 +63,7 @@ namespace elna::boot
* \c const qualifier used incorrectly — wrong position or
* duplicate.
*/
- class name_analysis_error final : public error
+ class const_qualifier_error final : public error
{
public:
enum class kind
@@ -77,7 +77,7 @@ namespace elna::boot
};
using payload_type = std::variant<not_initialized, kind>;
- name_analysis_error(const source_position position, payload_type payload);
+ const_qualifier_error(const source_position position, payload_type payload);
std::optional<std::pair<std::string, source_position>> note() const override;
std::string what() const override;
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index 03d589e..bf2149a 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -184,6 +184,19 @@ namespace elna::boot
};
/**
+ * Creates an error note pointing to a previous declaration.
+ *
+ * \param original Source position of the previous declaration.
+ * \param label Description what was declared previously.
+ * \return Error note if the position of the previous declaration is available.
+ */
+ std::optional<std::pair<std::string, source_position>> previous_declaration_note(
+ const std::optional<source_position>& original, std::string_view label = "previously declared here");
+
+ std::optional<std::pair<std::string, source_position>> identifier_list_note(
+ const std::vector<identifier>& identifiers);
+
+ /**
* Checks whether the givn object can be converted to a string using
* the .to_string() method.
*/
diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h
index 93e891a..52eec61 100644
--- a/include/elna/boot/type_check.h
+++ b/include/elna/boot/type_check.h
@@ -58,14 +58,8 @@ namespace elna::boot
{
integer_literal overflow;
};
- enum class kind {
- record_base,
- for_range,
- condition,
- constant_assignment,
- array_index,
- non_indexable,
- dereference_of_non_pointer
+ struct constant_assignment
+ {
};
using payload_type = std::variant<
expected_type,
@@ -74,7 +68,7 @@ namespace elna::boot
binary,
invalid_cast,
integer_literal_overflow,
- kind
+ constant_assignment
>;
type_mismatch_error(const source_position position,
@@ -87,6 +81,29 @@ namespace elna::boot
payload_type payload;
};
+ class type_requirement_error : public error
+ {
+ public:
+ enum class kind
+ {
+ record_base,
+ for_range,
+ condition,
+ array_index,
+ non_indexable,
+ dereference_of_non_pointer
+ };
+
+ type_requirement_error(const source_position position,
+ type actual, kind kind);
+
+ std::string what() const override;
+
+ private:
+ type actual;
+ kind m_kind;
+ };
+
/**
* Cyclic type declaration.
*/
@@ -95,7 +112,7 @@ namespace elna::boot
std::vector<std::string> cycle;
public:
- cyclic_declaration_error(const std::vector<std::string>& cycle, const source_position position);
+ cyclic_declaration_error(const source_position position, const std::vector<std::string>& cycle);
std::string what() const override;
};
@@ -106,12 +123,22 @@ namespace elna::boot
*/
class argument_count_error final : public error
{
+ public:
+ enum class kind
+ {
+ trait,
+ call,
+ array
+ };
+ private:
+ kind m_kind;
+ std::string applicand;
std::size_t expected;
std::size_t actual;
public:
- argument_count_error(std::size_t expected, std::size_t actual,
- const source_position position);
+ argument_count_error(const source_position position, kind kind,
+ std::string applicand, std::size_t expected, std::size_t actual);
std::string what() const override;
};
@@ -122,18 +149,15 @@ namespace elna::boot
class trait_error final : public error
{
public:
- struct argument_count
+ struct offset_not_field_name
{
- std::size_t expected;
- std::size_t actual;
};
- struct offset_not_field_name {};
struct unsupported_type
{
type actual;
};
- using payload_type = std::variant<argument_count, offset_not_field_name, unsupported_type>;
+ using payload_type = std::variant<offset_not_field_name, unsupported_type>;
trait_error(const source_position position, const std::string& trait_name,
payload_type payload);
diff --git a/include/elna/boot/validation.h b/include/elna/boot/validation.h
index 171ac1d..65972b7 100644
--- a/include/elna/boot/validation.h
+++ b/include/elna/boot/validation.h
@@ -30,19 +30,13 @@ namespace elna::boot
class validation_error final : public error
{
public:
- struct duplicate_case
- {
- source_position first;
- };
- using payload_type = std::variant<duplicate_case>;
-
- validation_error(const source_position position, payload_type payload);
+ validation_error(const source_position position, source_position first);
std::string what() const override;
std::optional<std::pair<std::string, source_position>> note() const override;
private:
- payload_type payload;
+ source_position first;
};
/**