diff options
Diffstat (limited to 'boot/type_check.cc')
| -rw-r--r-- | boot/type_check.cc | 64 |
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); + } + } + } } |
