aboutsummaryrefslogtreecommitdiff
path: root/boot/type_check.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/type_check.cc')
-rw-r--r--boot/type_check.cc68
1 files changed, 48 insertions, 20 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc
index c88a7d1..2bb0ddd 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -22,14 +22,30 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
- non_constant_initializer_error::non_constant_initializer_error(const source_position position)
- : error(position)
+ trait_error::trait_error(const source_position position, const std::string& trait_name,
+ payload_type payload)
+ : error(position), trait_name(trait_name), m_payload(payload)
{
}
- std::string non_constant_initializer_error::what() const
+ std::string trait_error::what() const
{
- return "Variable initializers must be constant expressions";
+ return std::visit([this](auto&& payload) -> std::string
+ {
+ 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
+ {
+ return "The second argument to the #" + this->trait_name + " trait must be a field name";
+ }
+ }, this->m_payload);
}
type_mismatch_error::type_mismatch_error(const source_position position,
@@ -453,22 +469,6 @@ namespace elna::boot
{
return;
}
- evaluator constant_evaluator(this->bag, this->target, this->evaluated_initializers);
- if (!constant_evaluator.evaluate(*declaration->initializer))
- {
- add_error<non_constant_initializer_error>(declaration->initializer->position());
- return;
- }
- // Record const variable initializers so later declarations
- // can chain through them.
- for (const auto& identifier : declaration->identifiers)
- {
- if (auto var = this->bag.lookup(identifier.name())->is_variable();
- resolve_aliases(var->symbol).get<constant_type>() != nullptr)
- {
- this->evaluated_initializers[identifier.name()] = declaration->initializer;
- }
- }
for (const identifier_definition& variable_identifier : declaration->identifiers)
{
auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();
@@ -864,4 +864,32 @@ namespace elna::boot
expression->lhs().type_decoration, expression->rhs().type_decoration, operation);
}
}
+
+ void type_analysis_visitor::visit(traits_expression *trait)
+ {
+ walking_visitor::visit(trait);
+
+ if (trait->name == "size" || trait->name == "alignment"
+ || trait->name == "min" || trait->name == "max")
+ {
+ if (trait->arguments.size() != 1)
+ {
+ add_error<trait_error>(trait->position(), trait->name.name(),
+ trait_error::argument_count{ .expected = 1, .actual = trait->arguments.size() });
+ }
+ }
+ else if (trait->name == "offset")
+ {
+ if (trait->arguments.size() != 2)
+ {
+ add_error<trait_error>(trait->position(), trait->name.name(),
+ trait_error::argument_count{ .expected = 2, .actual = trait->arguments.size() });
+ }
+ else if (trait->arguments.at(1)->is_named() == nullptr)
+ {
+ add_error<trait_error>(trait->arguments.at(1)->position(), trait->name.name(),
+ trait_error::offset_not_field_name{});
+ }
+ }
+ }
}