From df78b8ad3ebd263849eee6736fd78efe017522a4 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 6 Feb 2017 21:31:27 +0000 Subject: [PATCH] Make checking map key exists optional --- code/demo.odin | 4 ++-- src/check_decl.c | 2 +- src/check_expr.c | 24 ++++++++++++++++++++---- src/check_stmt.c | 7 ++----- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index c4e44aebd..90ac11858 100644 --- a/code/demo.odin +++ b/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; /* diff --git a/src/check_decl.c b/src/check_decl.c index 1cbfcacc6..b690799af 100644 --- a/src/check_decl.c +++ b/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) { diff --git a/src/check_expr.c b/src/check_expr.c index 112fae2af..b271a62f9 100644 --- a/src/check_expr.c +++ b/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; } diff --git a/src/check_stmt.c b/src/check_stmt.c index 83d3939e8..a77120737 100644 --- a/src/check_stmt.c +++ b/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