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.cc64
1 files changed, 64 insertions, 0 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc
index b310e34..d9f3071 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -200,6 +200,35 @@ namespace elna::boot
+ "' does not support trait '#" + trait_name + "'";
}
+ unary_operation_error::unary_operation_error(const source_position position,
+ type actual, unary_operator op)
+ : error(position), actual(actual), op(op)
+ {
+ }
+
+ char unary_operation_error::unary_operator_symbol(unary_operator op)
+ {
+ switch (op)
+ {
+ case unary_operator::reference:
+ return '@';
+ case unary_operator::negation:
+ return '~';
+ case unary_operator::minus:
+ return '-';
+ case unary_operator::plus:
+ return '+';
+ }
+ __builtin_unreachable();
+ }
+
+ std::string unary_operation_error::what() const
+ {
+ return "Type '" + actual.to_string()
+ + "' cannot be used with unary '"
+ + unary_operator_symbol(op) + "'";
+ }
+
/*
* Whether the type itself is constant or has a constant member at any
* nesting level, so that values of this type cannot be reassigned as a
@@ -597,4 +626,39 @@ namespace elna::boot
}
}
}
+
+ void type_analysis_visitor::visit(unary_expression *expression)
+ {
+ walking_visitor::visit(expression);
+
+ auto op = expression->operation();
+ type resolved = resolve_underlying_type(expression->operand().type_decoration);
+
+ if (op == unary_operator::plus)
+ {
+ if (!is_numeric_type(resolved))
+ {
+ add_error<unary_operation_error>(expression->position(),
+ expression->operand().type_decoration, op);
+ }
+ }
+ else if (op == unary_operator::minus)
+ {
+ if (!is_primitive_type(resolved, "Int")
+ && !is_primitive_type(resolved, "Float"))
+ {
+ add_error<unary_operation_error>(expression->position(),
+ expression->operand().type_decoration, op);
+ }
+ }
+ else if (op == unary_operator::negation)
+ {
+ if (!is_primitive_type(resolved, "Bool")
+ && !is_integral_type(resolved))
+ {
+ add_error<unary_operation_error>(expression->position(),
+ expression->operand().type_decoration, op);
+ }
+ }
+ }
}