From 24147a85f7a625a8189cbb5aed802c6c0e6516d6 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 19 Mar 2023 22:46:28 +0100 Subject: [PATCH] Allow unary plus. --- src/compiler/ast.c | 1 + src/compiler/enums.h | 1 + src/compiler/expr.c | 2 ++ src/compiler/llvm_codegen_expr.c | 3 +++ src/compiler/parse_expr.c | 2 +- src/compiler/sema_casts.c | 1 + src/compiler/sema_expr.c | 21 +++++++++++++++++---- src/version.h | 2 +- test/test_suite/expressions/plus_int.c3 | 20 ++++++++++++++++++++ 9 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 test/test_suite/expressions/plus_int.c3 diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 362e321f0..158adf7f5 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -340,6 +340,7 @@ UnaryOp unary_op[TOKEN_LAST + 1] = { [TOKEN_BIT_NOT] = UNARYOP_BITNEG, [TOKEN_BANG] = UNARYOP_NOT, [TOKEN_MINUS] = UNARYOP_NEG, + [TOKEN_PLUS] = UNARYOP_PLUS, [TOKEN_PLUSPLUS] = UNARYOP_INC, [TOKEN_MINUSMINUS] = UNARYOP_DEC, }; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index cdd14cfee..d621d7eb3 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -687,6 +687,7 @@ typedef enum UNARYOP_DEREF, UNARYOP_ADDR, UNARYOP_NEG, + UNARYOP_PLUS, UNARYOP_BITNEG, UNARYOP_NOT, UNARYOP_INC, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 90994b0ee..aa82de60f 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -307,6 +307,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) if (eval_kind == CONSTANT_EVAL_CONSTANT_VALUE || eval_kind == CONSTANT_EVAL_LOCAL_INIT) return false; expr = expr->unary_expr.expr; goto RETRY; + case UNARYOP_PLUS: case UNARYOP_NEG: case UNARYOP_BITNEG: case UNARYOP_NOT: @@ -685,6 +686,7 @@ bool expr_is_pure(Expr *expr) case UNARYOP_NEG: case UNARYOP_BITNEG: case UNARYOP_NOT: + case UNARYOP_PLUS: return expr_is_pure(expr->unary_expr.expr); } UNREACHABLE diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 644d5a03a..000e20f61 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2332,6 +2332,9 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) { case UNARYOP_ERROR: FATAL_ERROR("Illegal unary op %s", expr->unary_expr.operator); + case UNARYOP_PLUS: + // Folded + UNREACHABLE case UNARYOP_NOT: llvm_emit_expr(c, value, inner); if (type_flat_is_vector(type)) diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index f8e825001..a6797d5a8 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -1770,7 +1770,7 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_BANGBANG] = { NULL, parse_force_unwrap_expr, PREC_CALL }, [TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL }, [TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE }, - [TOKEN_PLUS] = { NULL, parse_binary, PREC_ADDITIVE }, + [TOKEN_PLUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE }, [TOKEN_DIV] = { NULL, parse_binary, PREC_MULTIPLICATIVE }, [TOKEN_MOD] = { NULL, parse_binary, PREC_MULTIPLICATIVE }, [TOKEN_STAR] = { parse_unary_expr, parse_binary, PREC_MULTIPLICATIVE }, diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 249f50d31..e4a32a0d3 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -866,6 +866,7 @@ RETRY: case UNARYOP_DEREF: // Check sizes. goto CHECK_SIZE; + case UNARYOP_PLUS: case UNARYOP_NEG: case UNARYOP_BITNEG: case UNARYOP_INC: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 642eb19f1..73e3b975a 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -83,7 +83,7 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr * // -- unary static inline bool sema_expr_analyse_addr(SemaContext *context, Expr *expr); -static inline bool sema_expr_analyse_neg(SemaContext *context, Expr *expr); +static inline bool sema_expr_analyse_neg_plus(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_bit_not(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_not(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_deref(SemaContext *context, Expr *expr); @@ -5506,12 +5506,13 @@ static inline bool sema_expr_analyse_addr(SemaContext *context, Expr *expr) } /** - * Test -a + * Test -a / +a */ -static inline bool sema_expr_analyse_neg(SemaContext *context, Expr *expr) +static inline bool sema_expr_analyse_neg_plus(SemaContext *context, Expr *expr) { // 1. Check the inner expression Expr *inner = expr->unary_expr.expr; + bool is_plus = expr->unary_expr.operator == UNARYOP_PLUS; if (!sema_analyse_expr(context, inner)) return false; if (expr->unary_expr.widen && !cast_widen_top_down(context, inner, expr->type)) return false; @@ -5519,6 +5520,11 @@ static inline bool sema_expr_analyse_neg(SemaContext *context, Expr *expr) Type *no_fail = type_no_optional(inner->type); if (!type_may_negate(no_fail)) { + if (is_plus) + { + SEMA_ERROR(expr, "Cannot use '+' with an expression of type %s.", type_quoted_error_string(no_fail)); + return false; + } SEMA_ERROR(expr, "Cannot negate an expression of type %s.", type_quoted_error_string(no_fail)); return false; } @@ -5526,6 +5532,12 @@ static inline bool sema_expr_analyse_neg(SemaContext *context, Expr *expr) Type *result_type = cast_numeric_arithmetic_promotion(no_fail); if (!cast_implicit(context, inner, result_type)) return false; + // If it's a plus, we simply replace the inner with the outer. + if (is_plus) + { + expr_replace(expr, inner); + return true; + } // 4. If it's non-const, we're done. if (!sema_constant_fold_ops(inner)) { @@ -5946,7 +5958,8 @@ static inline bool sema_expr_analyse_unary(SemaContext *context, Expr *expr) case UNARYOP_ADDR: return sema_expr_analyse_addr(context, expr); case UNARYOP_NEG: - return sema_expr_analyse_neg(context, expr); + case UNARYOP_PLUS: + return sema_expr_analyse_neg_plus(context, expr); case UNARYOP_BITNEG: return sema_expr_analyse_bit_not(context, expr); case UNARYOP_NOT: diff --git a/src/version.h b/src/version.h index 7d988d607..867abd511 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.112" \ No newline at end of file +#define COMPILER_VERSION "0.4.113" \ No newline at end of file diff --git a/test/test_suite/expressions/plus_int.c3 b/test/test_suite/expressions/plus_int.c3 new file mode 100644 index 000000000..edf4113d2 --- /dev/null +++ b/test/test_suite/expressions/plus_int.c3 @@ -0,0 +1,20 @@ +fn void test1() +{ + short! a = 1; + try? +a; + short b = +a; // #error: 'int!' to 'short'. +} + +fn void test2() +{ + int! a = 1; + try? +a; + int b = +a; // #error: 'int!' to 'int' +} + +fn void test3() +{ + long! a = 1; + try? +a; + long b = +a; // #error: 'long!' to 'long' +}