Browse Source

Remove the old switch/for semantics entirely and enforce `switch &x in y`

gingerBill 1 year ago
parent
commit
a344bc4c0e
3 changed files with 15 additions and 63 deletions
  1. 13 33
      src/check_expr.cpp
  2. 2 28
      src/check_stmt.cpp
  3. 0 2
      src/entity.cpp

+ 13 - 33
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);
 		}
 

+ 2 - 28
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<Entity *>(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) {

+ 0 - 2
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,
 };