Sfoglia il codice sorgente

Make checking map key exists optional

Ginger Bill 8 anni fa
parent
commit
df78b8ad3e
4 ha cambiato i file con 25 aggiunte e 12 eliminazioni
  1. 2 2
      code/demo.odin
  2. 1 1
      src/check_decl.c
  3. 20 4
      src/check_expr.c
  4. 2 5
      src/check_stmt.c

+ 2 - 2
code/demo.odin

@@ -18,14 +18,14 @@ main :: proc() {
 	m["a"] = 56;
 	m["b"] = 13453;
 	m["c"] = 7654;
-	c, ok := m["c"];
+	c := m["c"];
+	_, ok := m["c"];
 	assert(ok && c == 7654);
 
 	for val, key in m {
 		fmt.printf("m[\"%s\"] == %v\n", key, val);
 	}
 
-
 	// fm: map[128, int]f32;
 
 /*

+ 1 - 1
src/check_decl.c

@@ -63,7 +63,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 	// an extra allocation
 	ArrayOperand operands = {0};
 	array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
-	check_unpack_arguments(c, &operands, inits);
+	check_unpack_arguments(c, lhs_count, &operands, inits, true);
 
 	isize rhs_count = operands.count;
 	for_array(i, operands) {

+ 20 - 4
src/check_expr.c

@@ -2676,7 +2676,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 		gbString op_str   = expr_to_string(op_expr);
 		gbString type_str = type_to_string(operand->type);
 		gbString sel_str  = expr_to_string(selector);
-		error_node(op_expr, "`%s` (`%s`) has no field `%s`", op_str, type_str, sel_str);
+		error_node(op_expr, "`%s` of type `%s` has no field `%s`", op_str, type_str, sel_str);
 		gb_string_free(sel_str);
 		gb_string_free(type_str);
 		gb_string_free(op_str);
@@ -3824,12 +3824,28 @@ int valid_proc_and_score_cmp(void const *a, void const *b) {
 
 typedef Array(Operand) ArrayOperand;
 
-void check_unpack_arguments(Checker *c, ArrayOperand *operands, AstNodeArray args) {
+void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray args, bool allow_map_ok) {
 	for_array(i, args) {
 		Operand o = {0};
 		check_multi_expr(c, &o, args.e[i]);
 
 		if (o.type == NULL || o.type->kind != Type_Tuple) {
+			if (o.mode == Addressing_MapIndex &&
+			    allow_map_ok &&
+			    lhs_count == 2 &&
+			    args.count == 1) {
+				Type *tuple = make_map_tuple_type(c->allocator, o.type);
+				add_type_and_value(&c->info, o.expr, o.mode, tuple, o.value);
+
+				Operand val = o;
+				Operand ok = o;
+				val.mode = Addressing_Value;
+				ok.mode  = Addressing_Value;
+				ok.type  = t_bool;
+				array_add(operands, val);
+				array_add(operands, ok);
+				continue;
+			}
 			array_add(operands, o);
 		} else {
 			TypeTuple *tuple = &o.type->Tuple;
@@ -3848,7 +3864,7 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod
 
 	ArrayOperand operands;
 	array_init_reserve(&operands, heap_allocator(), 2*ce->args.count);
-	check_unpack_arguments(c, &operands, ce->args);
+	check_unpack_arguments(c, -1, &operands, ce->args, false);
 
 	if (operand->mode == Addressing_Overload) {
 		GB_ASSERT(operand->overload_entities != NULL &&
@@ -4991,7 +5007,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 				goto error;
 			}
 			o->mode = Addressing_MapIndex;
-			o->type = make_map_tuple_type(c->allocator, t->Map.value);
+			o->type = t->Map.value;
 			o->expr = node;
 			return Expr_Expr;
 		}

+ 2 - 5
src/check_stmt.c

@@ -262,11 +262,8 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 		return NULL;
 	case Addressing_Variable:
 		break;
-	case Addressing_MapIndex: {
-		Type *t = base_type(assignment_type); GB_ASSERT(is_type_tuple(t));
-		t = t->Tuple.variables[0]->type;
-		assignment_type = t;
-	} break;
+	case Addressing_MapIndex:
+		break;
 	default: {
 		if (op_b.expr->kind == AstNode_SelectorExpr) {
 			// NOTE(bill): Extra error checks