From ea0124433aed498c466d576fda659eb3e59c83f8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 26 Jul 2024 14:34:08 +0200 Subject: [PATCH] Remove "EXPR_GROUP" to simplify the code somewhat. --- src/compiler/compiler_internal.h | 4 +- src/compiler/copying.c | 1 - src/compiler/enums.h | 1 - src/compiler/expr.c | 8 --- src/compiler/llvm_codegen_expr.c | 1 - src/compiler/parse_expr.c | 43 +++++++++----- src/compiler/sema_casts.c | 1 - src/compiler/sema_expr.c | 99 +++++++++++++------------------- src/compiler/sema_liveness.c | 1 - src/compiler/sema_stmts.c | 4 -- 10 files changed, 72 insertions(+), 91 deletions(-) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 3a0cd3aef..0c911fc3c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -766,7 +766,7 @@ typedef struct ExprId cond; ExprId then_expr; // May be null for elvis! ExprId else_expr; - bool widen : 1; + bool grouped : 1; } ExprTernary; typedef struct @@ -774,6 +774,7 @@ typedef struct ExprId left; ExprId right; BinaryOp operator : 8; + bool grouped : 1; } ExprBinary; typedef struct @@ -3411,7 +3412,6 @@ INLINE void expr_set_span(Expr *expr, SourceSpan loc) case EXPR_OPTIONAL: case EXPR_FORCE_UNWRAP: case EXPR_GENERIC_IDENT: - case EXPR_GROUP: case EXPR_HASH_IDENT: case EXPR_IDENTIFIER: case EXPR_LAMBDA: diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 5673bbd0e..4e5b58c1b 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -432,7 +432,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) return expr; case EXPR_FORCE_UNWRAP: case EXPR_OPTIONAL: - case EXPR_GROUP: case EXPR_STRINGIFY: case EXPR_CT_EVAL: case EXPR_CT_IS_CONST: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index a3ddcca2c..72d0eff7e 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -256,7 +256,6 @@ typedef enum EXPR_EXPR_BLOCK, EXPR_FORCE_UNWRAP, EXPR_GENERIC_IDENT, - EXPR_GROUP, EXPR_HASH_IDENT, EXPR_IDENTIFIER, EXPR_INITIALIZER_LIST, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 5e4338434..60739d60c 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -77,8 +77,6 @@ bool expr_may_addr(Expr *expr) case EXPR_BITACCESS: case EXPR_ACCESS: return expr_may_addr(expr->access_expr.parent); - case EXPR_GROUP: - return expr_may_addr(expr->inner_expr); case EXPR_SUBSCRIPT: case EXPR_SLICE: return true; @@ -251,7 +249,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) expr = exprptr(expr->typeid_info_expr.parent); goto RETRY; case EXPR_OPTIONAL: - case EXPR_GROUP: expr = expr->inner_expr; goto RETRY; case EXPR_DEFAULT_ARG: @@ -790,8 +787,6 @@ bool expr_is_pure(Expr *expr) return false; case EXPR_DEFAULT_ARG: return expr_is_pure(expr->default_arg_expr.inner); - case EXPR_GROUP: - return expr_is_pure(expr->inner_expr); } UNREACHABLE } @@ -802,9 +797,6 @@ bool expr_is_simple(Expr *expr, bool to_float) RETRY: switch (expr->expr_kind) { - case EXPR_GROUP: - expr = expr->inner_expr; - goto RETRY; case EXPR_TERNARY: return exprid_is_simple(expr->ternary_expr.else_expr, to_float) && exprid_is_simple(expr->ternary_expr.then_expr, to_float); case EXPR_RETHROW: diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 4b0dc1ff8..becaab161 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -7153,7 +7153,6 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) llvm_emit_rethrow_expr(c, value, expr); return; case EXPR_TYPEID: - case EXPR_GROUP: case EXPR_SUBSCRIPT_ASSIGN: // These are folded in the semantic analysis step. UNREACHABLE diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index f7ca8d7ca..dee6e8e1d 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -730,26 +730,41 @@ static Expr *parse_ternary_expr(ParseContext *c, Expr *left_side) static Expr *parse_grouping_expr(ParseContext *c, Expr *left) { assert(!left && "Unexpected left hand side"); - Expr *expr = EXPR_NEW_TOKEN(EXPR_GROUP); + Expr *expr; advance_and_verify(c, TOKEN_LPAREN); - ASSIGN_EXPR_OR_RET(expr->inner_expr, parse_expr(c), poisoned_expr); + ASSIGN_EXPR_OR_RET(expr, parse_expr(c), poisoned_expr); CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); // Look at what follows. - if (expr->inner_expr->expr_kind == EXPR_TYPEINFO) + switch (expr->expr_kind) { - TypeInfo *info = expr->inner_expr->type_expr; - if (tok_is(c, TOKEN_LBRACE) && info->resolve_status != RESOLVE_DONE) + case EXPR_TYPEINFO: { - PRINT_ERROR_HERE("Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type."); - return poisoned_expr; - } - // Create a cast expr - if (rules[c->tok].prefix) - { - ASSIGN_EXPRID_OR_RET(expr->cast_expr.expr, parse_precedence(c, PREC_CALL), poisoned_expr); - expr->expr_kind = EXPR_CAST; - expr->cast_expr.type_info = type_infoid(info); + TypeInfo *info = expr->type_expr; + if (tok_is(c, TOKEN_LBRACE) && info->resolve_status != RESOLVE_DONE) + { + PRINT_ERROR_HERE("Unexpected start of a block '{' here. If you intended a compound literal, remove the () around the type."); + return poisoned_expr; + } + // Create a cast expr + if (rules[c->tok].prefix) + { + ASSIGN_EXPRID_OR_RET(ExprId inner, parse_precedence(c, PREC_CALL), poisoned_expr); + SourceSpan span = expr->span; + *expr = (Expr) {.expr_kind = EXPR_CAST, + .span = span, + .cast_expr.type_info = type_infoid(info), + .cast_expr.expr = inner}; + } + break; } + case EXPR_BINARY: + expr->binary_expr.grouped = true; + break; + case EXPR_TERNARY: + expr->ternary_expr.grouped = true; + break; + default: + break; } RANGE_EXTEND_PREV(expr); return expr; diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 697366359..8c187aab3 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -517,7 +517,6 @@ RETRY: case EXPR_POST_UNARY: expr = expr->unary_expr.expr; goto RETRY; - case EXPR_GROUP: case EXPR_FORCE_UNWRAP: expr = expr->inner_expr; goto RETRY; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 1124cb418..c6b753d2b 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -35,7 +35,7 @@ static inline bool sema_constant_fold_ops(Expr *expr); static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, SubscriptEval eval_type); static inline bool sema_expr_analyse_pointer_offset(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr); -static inline bool sema_expr_analyse_group(SemaContext *context, Expr *expr); + static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bool *missing_ref); static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, bool throw_error); @@ -189,8 +189,8 @@ static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *e static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr); static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr); -static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, bool was_group, Expr *identifier, bool *missing_ref); -static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, bool was_group, Expr *identifier, bool *missing_ref); +static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, Expr *identifier, bool *missing_ref); +static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, Expr *identifier, bool *missing_ref); static inline bool sema_expr_fold_to_member(Expr *expr, Expr *parent, Decl *member); static inline bool sema_expr_fold_to_index(Expr *expr, Expr *parent, Range range); static inline void sema_expr_flatten_const_ident(Expr *expr); @@ -532,8 +532,6 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_BITACCESS: case EXPR_ACCESS: return sema_binary_is_expr_lvalue(context, top_expr, expr->access_expr.parent); - case EXPR_GROUP: - return sema_binary_is_expr_lvalue(context, top_expr, expr->inner_expr); case EXPR_SUBSCRIPT: case EXPR_SLICE: case EXPR_SUBSCRIPT_ADDR: @@ -658,8 +656,6 @@ static bool expr_may_ref(Expr *expr) case EXPR_BITACCESS: case EXPR_ACCESS: return expr_may_ref(expr->access_expr.parent); - case EXPR_GROUP: - return expr_may_ref(expr->inner_expr); case EXPR_SUBSCRIPT: case EXPR_SLICE: case EXPR_SUBSCRIPT_ADDR: @@ -3143,13 +3139,6 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) } -static inline bool sema_expr_analyse_group(SemaContext *context, Expr *expr) -{ - if (!sema_analyse_expr(context, expr->inner_expr)) return false; - *expr = *expr->inner_expr; - return true; -} - /** * 1. .A -> It is an enum constant. * 2. .foo -> It is a function. @@ -3260,8 +3249,7 @@ static inline bool sema_expr_replace_with_enum_name_array(SemaContext *context, return sema_analyse_expr(context, enum_array_expr); } -static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, bool was_group, - Expr *identifier, bool *missing_ref) +static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, Expr *identifier, bool *missing_ref) { assert(identifier->expr_kind == EXPR_IDENTIFIER); Type *canonical = parent_type->canonical; @@ -3371,9 +3359,7 @@ MISSING_REF: return false; } -static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, - Expr *parent, bool was_group, Expr *identifier, - bool *missing_ref) +static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, Expr *identifier, bool *missing_ref) { assert(identifier->expr_kind == EXPR_IDENTIFIER); @@ -4313,7 +4299,6 @@ static inline void sema_expr_flatten_const_ident(Expr *expr) static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bool *missing_ref) { Expr *parent = expr->access_expr.parent; - bool was_group = parent->expr_kind == EXPR_GROUP; if (missing_ref) *missing_ref = false; // 1. Resolve the left hand @@ -4369,15 +4354,15 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo // 2. If our left-hand side is a type, e.g. MyInt.abc, handle this here. if (parent->expr_kind == EXPR_TYPEINFO) { - return sema_expr_analyse_type_access(context, expr, parent->type_expr->type, was_group, identifier, missing_ref); + return sema_expr_analyse_type_access(context, expr, parent->type_expr->type, identifier, missing_ref); } if (parent->expr_kind == EXPR_IDENTIFIER && parent->type->type_kind == TYPE_FUNC_RAW) { - return sema_expr_analyse_type_access(context, expr, parent->type, was_group, identifier, missing_ref); + return sema_expr_analyse_type_access(context, expr, parent->type, identifier, missing_ref); } if (expr_is_const_member(parent)) { - return sema_expr_analyse_member_access(context, expr, parent, was_group, identifier, missing_ref); + return sema_expr_analyse_member_access(context, expr, parent, identifier, missing_ref); } // 6. Copy failability @@ -5112,22 +5097,21 @@ static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Ex static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right) { // 1. Evaluate left side - if (left->expr_kind == EXPR_CT_IDENT) + switch (left->expr_kind) { - return sema_expr_analyse_ct_identifier_assign(context, expr, left, right); - } - - if (left->expr_kind == EXPR_TYPEINFO) - { - return sema_expr_analyse_ct_type_identifier_assign(context, expr, left, right); - } - if (left->expr_kind == EXPR_SUBSCRIPT) - { - if (!sema_expr_analyse_subscript(context, left, SUBSCRIPT_EVAL_ASSIGN)) return false; - } - else - { - if (!sema_analyse_expr_lvalue(context, left)) return false; + case EXPR_CT_IDENT: + // $foo = ... + return sema_expr_analyse_ct_identifier_assign(context, expr, left, right); + case EXPR_TYPEINFO: + // $Foo = ... + return sema_expr_analyse_ct_type_identifier_assign(context, expr, left, right); + case EXPR_SUBSCRIPT: + // abc[...] = ... + if (!sema_expr_analyse_subscript(context, left, SUBSCRIPT_EVAL_ASSIGN)) return false; + break; + default: + if (!sema_analyse_expr_lvalue(context, left)) return false; + break; } // 2. Check assignability if (!sema_expr_check_assign(context, left)) return false; @@ -6430,8 +6414,6 @@ static const char *sema_addr_check_may_take(Expr *inner) } return sema_addr_check_may_take(inner->access_expr.parent); } - case EXPR_GROUP: - return sema_addr_check_may_take(inner->inner_expr); case EXPR_SUBSCRIPT: return sema_addr_check_may_take(exprptr(inner->subscript_expr.expr)); case EXPR_TYPEINFO: @@ -6452,15 +6434,10 @@ static inline bool sema_expr_analyse_addr(SemaContext *context, Expr *expr, bool { // 1. Evaluate the expression Expr *inner = expr->unary_expr.expr; - REDO: switch (inner->expr_kind) { case EXPR_POISONED: return false; - case EXPR_GROUP: - // We want to collapse any grouping here. - expr_replace(inner, inner->inner_expr); - goto REDO; case EXPR_SUBSCRIPT: inner->expr_kind = EXPR_SUBSCRIPT_ADDR; if (failed_ref) @@ -6777,6 +6754,11 @@ static inline bool sema_expr_analyse_taddr(SemaContext *context, Expr *expr, boo return true; } +INLINE bool expr_is_ungrouped_binary(Expr *expr) +{ + return expr->expr_kind == EXPR_BINARY && !expr->binary_expr.grouped; +} + static bool sema_binary_check_unclear_op_precedence(Expr *left_side, Expr * main_expr, Expr *right_side) { static int BINOP_PREC_REQ[BINARYOP_LAST + 1] = { @@ -6799,7 +6781,7 @@ static bool sema_binary_check_unclear_op_precedence(Expr *left_side, Expr * main BinaryOp main_op = main_expr->binary_expr.operator; int precedence_main = BINOP_PREC_REQ[main_op]; - if (left_side->expr_kind == EXPR_BINARY) + if (expr_is_ungrouped_binary(left_side)) { int left_op = left_side->binary_expr.operator; int precedence_left = BINOP_PREC_REQ[left_op]; @@ -6809,7 +6791,7 @@ static bool sema_binary_check_unclear_op_precedence(Expr *left_side, Expr * main if (precedence_left != 1 || left_op != main_op) return true; } } - if (right_side->expr_kind == EXPR_BINARY) + if (expr_is_ungrouped_binary(right_side)) { int right_op = right_side->binary_expr.operator; int precedence_right = BINOP_PREC_REQ[right_op]; @@ -6823,12 +6805,17 @@ static bool sema_binary_check_unclear_op_precedence(Expr *left_side, Expr * main } +INLINE bool expr_is_ungrouped_ternary(Expr *expr) +{ + return expr->expr_kind == EXPR_TERNARY && !expr->ternary_expr.grouped; +} + static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr) { Expr *lhs = exprptr(expr->binary_expr.left); bool lhs_is_embed = lhs->expr_kind == EXPR_EMBED; Expr *rhs = exprptr(expr->binary_expr.right); - if (lhs->expr_kind == EXPR_TERNARY || rhs->expr_kind == EXPR_TERNARY) + if (expr_is_ungrouped_ternary(lhs) || expr_is_ungrouped_ternary(rhs)) { SEMA_ERROR(expr, "Unclear precedence using ternary with ??, please use () to remove ambiguity."); return false; @@ -8295,7 +8282,6 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr REMINDER("Check if these should be analysed"); FALLTHROUGH; // Above needs to be analysed - case EXPR_GROUP: case EXPR_INITIALIZER_LIST: case EXPR_DESIGNATED_INITIALIZER_LIST: case EXPR_ASM: @@ -9082,8 +9068,6 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) return sema_expr_analyse_subscript(context, expr, SUBSCRIPT_EVAL_VALUE); case EXPR_SUBSCRIPT_ADDR: return sema_expr_analyse_subscript(context, expr, SUBSCRIPT_EVAL_REF); - case EXPR_GROUP: - return sema_expr_analyse_group(context, expr); case EXPR_BITACCESS: case EXPR_SUBSCRIPT_ASSIGN: UNREACHABLE @@ -9103,18 +9087,17 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) bool sema_analyse_cond_expr(SemaContext *context, Expr *expr, CondResult *result) { - if (expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator == BINARYOP_ASSIGN) + if (expr_is_ungrouped_binary(expr) && expr->binary_expr.operator == BINARYOP_ASSIGN) { - SEMA_ERROR(expr, "Assignment expressions must be enclosed in an extra () in conditionals."); - return false; + RETURN_SEMA_ERROR(expr, "Assignment expressions must be enclosed in an extra () in conditionals."); } if (!sema_analyse_expr(context, expr)) return false; if (IS_OPTIONAL(expr)) { - SEMA_ERROR(expr, "An optional %s cannot be implicitly converted to a regular boolean value, use '@ok()' " - "and '@catch()' to conditionally execute on success or failure.", - type_quoted_error_string(expr->type)); - return false; + RETURN_SEMA_ERROR(expr, "An optional %s cannot be implicitly converted to a regular boolean value, " + "use '@ok()' and '@catch()' to conditionally execute on success " + "or failure.", + type_quoted_error_string(expr->type)); } if (!cast_explicit(context, expr, type_bool)) return false; if (expr_is_const_bool(expr)) diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index eb87dc8eb..97f2dbb16 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -255,7 +255,6 @@ RETRY: switch (expr->expr_kind) { case EXPR_SUBSCRIPT_ASSIGN: - case EXPR_GROUP: case EXPR_OPERATOR_CHARS: case EXPR_VASPLAT: case EXPR_POISONED: diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index f27cb816e..f44dedcec 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -649,7 +649,6 @@ static inline bool sema_expr_valid_try_expression(Expr *expr) case EXPR_OPTIONAL: case EXPR_FORCE_UNWRAP: case EXPR_GENERIC_IDENT: - case EXPR_GROUP: case EXPR_HASH_IDENT: case EXPR_IDENTIFIER: case EXPR_INITIALIZER_LIST: @@ -1432,9 +1431,6 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen bool value_by_ref = statement->foreach_stmt.value_by_ref; bool success = true; - // First fold the enumerator expression, removing any () around it. - while (enumerator->expr_kind == EXPR_GROUP) enumerator = enumerator->inner_expr; - bool iterator_based = false; // Conditional scope start