From a344bc4c0e672d9740f5777dae862723fe269973 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 16 May 2024 14:39:16 +0100 Subject: [PATCH] Remove the old switch/for semantics entirely and enforce `switch &x in y` --- src/check_expr.cpp | 46 +++++++++++++--------------------------------- src/check_stmt.cpp | 30 ++---------------------------- src/entity.cpp | 2 -- 3 files changed, 15 insertions(+), 63 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6a293a97e..c44232dab 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2440,32 +2440,6 @@ gb_internal bool check_is_not_addressable(CheckerContext *c, Operand *o) { return o->mode != Addressing_Variable && o->mode != Addressing_SoaVariable; } -gb_internal void check_old_for_or_switch_value_usage(Ast *expr) { - Entity *e = entity_of_node(expr); - if (e != nullptr && (e->flags & EntityFlag_OldForOrSwitchValue) != 0) { - GB_ASSERT(e->kind == Entity_Variable); - - ERROR_BLOCK(); - - if ((e->flags & EntityFlag_ForValue) != 0) { - Type *parent_type = type_deref(e->Variable.for_loop_parent_type); - - error(expr, "Assuming a for-in defined value is addressable as the iterable is passed by value has been disallowed."); - - if (is_type_map(parent_type)) { - error_line("\tSuggestion: Prefer doing 'for key, &%.*s in ...'\n", LIT(e->token.string)); - } else { - error_line("\tSuggestion: Prefer doing 'for &%.*s in ...'\n", LIT(e->token.string)); - } - } else { - GB_ASSERT((e->flags & EntityFlag_SwitchValue) != 0); - - error(expr, "Assuming a switch-in defined value is addressable as the iterable is passed by value has been disallowed."); - error_line("\tSuggestion: Prefer doing 'switch &%.*s in ...'\n", LIT(e->token.string)); - } - } -} - gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) { switch (op.kind) { case Token_And: { // Pointer address @@ -2493,7 +2467,10 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * { ERROR_BLOCK(); error(op, "Cannot take the pointer address of '%s'", str); - if (e != nullptr && (e->flags & EntityFlag_ForValue) != 0) { + if (e == nullptr) { + break; + } + if ((e->flags & EntityFlag_ForValue) != 0) { Type *parent_type = type_deref(e->Variable.for_loop_parent_type); if (parent_type != nullptr && is_type_string(parent_type)) { @@ -2503,9 +2480,17 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * } else { error_line("\tSuggestion: Did you want to pass the iterable value to the for statement by pointer to get addressable semantics?\n"); } + + if (is_type_map(parent_type)) { + error_line("\t Prefer doing 'for key, &%.*s in ...'\n", LIT(e->token.string)); + } else { + error_line("\t Prefer doing 'for &%.*s in ...'\n", LIT(e->token.string)); + } } - if (e != nullptr && (e->flags & EntityFlag_SwitchValue) != 0) { + if ((e->flags & EntityFlag_SwitchValue) != 0) { error_line("\tSuggestion: Did you want to pass the value to the switch statement by pointer to get addressable semantics?\n"); + + error_line("\t Prefer doing 'switch &%.*s in ...'\n", LIT(e->token.string)); } } break; @@ -2527,11 +2512,6 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * o->type = alloc_type_pointer(o->type); } } else { - if (ast_node_expect(node, Ast_UnaryExpr)) { - ast_node(ue, UnaryExpr, node); - check_old_for_or_switch_value_usage(ue->expr); - } - o->type = alloc_type_pointer(o->type); } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 875503874..0267bdf80 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -501,7 +501,6 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O return nullptr; case Addressing_Variable: - check_old_for_or_switch_value_usage(lhs->expr); break; case Addressing_MapIndex: { @@ -523,9 +522,8 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O break; } - case Addressing_Context: { + case Addressing_Context: break; - } case Addressing_SoaVariable: break; @@ -1328,7 +1326,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ } } - bool is_ptr = is_type_pointer(x.type); // NOTE(bill): Check for multiple defaults Ast *first_default = nullptr; @@ -1447,15 +1444,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ } bool is_reference = is_addressed; - bool old_style = false; - - if (!is_reference && - is_ptr && - cc->list.count == 1 && - case_type != nullptr) { - is_reference = true; - old_style = true; - } if (cc->list.count > 1 || saw_nil) { case_type = nullptr; @@ -1477,9 +1465,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ if (!is_reference) { tag_var->flags |= EntityFlag_Value; } - if (old_style) { - tag_var->flags |= EntityFlag_OldForOrSwitchValue; - } add_entity(ctx, ctx->scope, lhs, tag_var); add_entity_use(ctx, lhs, tag_var); add_implicit_entity(ctx, stmt, tag_var); @@ -1618,7 +1603,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) auto entities = array_make(temporary_allocator(), 0, 2); bool is_map = false; bool is_bit_set = false; - bool use_by_reference_for_value = false; bool is_soa = false; bool is_reverse = rs->reverse; @@ -1679,7 +1663,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) } } } - bool is_ptr = is_type_pointer(operand.type); Type *t = base_type(type_deref(operand.type)); switch (t->kind) { @@ -1719,32 +1702,27 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) break; case Type_EnumeratedArray: - if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->EnumeratedArray.elem); array_add(&vals, t->EnumeratedArray.index); break; case Type_Array: - if (is_ptr) use_by_reference_for_value = true; - if (!is_ptr) is_possibly_addressable = operand.mode == Addressing_Variable; + is_possibly_addressable = operand.mode == Addressing_Variable; array_add(&vals, t->Array.elem); array_add(&vals, t_int); break; case Type_DynamicArray: - if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->DynamicArray.elem); array_add(&vals, t_int); break; case Type_Slice: - if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->Slice.elem); array_add(&vals, t_int); break; case Type_Map: - if (is_ptr) use_by_reference_for_value = true; is_map = true; array_add(&vals, t->Map.key); array_add(&vals, t->Map.value); @@ -1817,7 +1795,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) case Type_Struct: if (t->Struct.soa_kind != StructSoa_None) { is_soa = true; - if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->Struct.soa_elem); array_add(&vals, t_int); } @@ -1894,9 +1871,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) char const *idx_name = is_map ? "key" : is_bit_set ? "element" : "index"; error(token, "The %s variable '%.*s' cannot be made addressable", idx_name, LIT(str)); } - } else if (i == addressable_index && use_by_reference_for_value) { - entity->flags |= EntityFlag_OldForOrSwitchValue; - entity->flags &= ~EntityFlag_Value; } if (is_soa) { if (i == 0) { diff --git a/src/entity.cpp b/src/entity.cpp index 60ca208ec..8a7417006 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -85,8 +85,6 @@ enum EntityFlag : u64 { EntityFlag_Require = 1ull<<50, EntityFlag_ByPtr = 1ull<<51, // enforce parameter is passed by pointer - EntityFlag_OldForOrSwitchValue = 1ull<<52, - EntityFlag_Overridden = 1ull<<63, };