diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-14 16:37:24 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-14 16:37:24 +0000 |
| commit | 8b5e3428a1e569abf763e63e859754e767e107e7 (patch) | |
| tree | 302a0cd18b18436feeac7bf50d0d430b0368251a /src | |
| parent | d1f65097c48afe6d869949cc5ede76a8b14401a9 (diff) | |
Optional ok for `union_cast` (similar to map indices)
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_decl.c | 11 | ||||
| -rw-r--r-- | src/check_expr.c | 33 | ||||
| -rw-r--r-- | src/check_stmt.c | 40 | ||||
| -rw-r--r-- | src/checker.c | 25 | ||||
| -rw-r--r-- | src/ir.c | 41 |
5 files changed, 76 insertions, 74 deletions
diff --git a/src/check_decl.c b/src/check_decl.c index ebee92b5e..bc49e36c1 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -72,25 +72,14 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra } } - isize max = gb_min(lhs_count, rhs_count); for (isize i = 0; i < max; i++) { check_init_variable(c, lhs[i], &operands.e[i], context_name); } - if (rhs_count > 0 && lhs_count != rhs_count) { error(lhs[0]->token, "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); } -#if 0 - if (lhs[0]->kind == Entity_Variable && - lhs[0]->Variable.is_let) { - if (lhs_count != rhs_count) { - error(lhs[0]->token, "`let` variables must be initialized, `%td` = `%td`", lhs_count, rhs_count); - } - } -#endif - gb_temp_arena_memory_end(tmp); } diff --git a/src/check_expr.c b/src/check_expr.c index 355f4016e..a93165574 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -265,8 +265,6 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n } - - if (type == NULL) { return; } @@ -1115,7 +1113,7 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { return 0; } -Type *make_map_tuple_type(gbAllocator a, Type *value) { +Type *make_optional_ok_type(gbAllocator a, Type *value) { Type *t = make_type_tuple(a); t->Tuple.variables = gb_alloc_array(a, Entity *, 2); t->Tuple.variable_count = 2; @@ -1221,7 +1219,7 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { type->Map.generated_struct_type = generated_struct_type; } - type->Map.lookup_result_type = make_map_tuple_type(a, value); + type->Map.lookup_result_type = make_optional_ok_type(a, value); // error_node(node, "`map` types are not yet implemented"); } @@ -3821,17 +3819,15 @@ int valid_proc_and_score_cmp(void const *a, void const *b) { typedef Array(Operand) ArrayOperand; -void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray args, bool allow_map_ok) { - for_array(i, args) { +void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) { + for_array(i, rhs) { Operand o = {0}; - check_multi_expr(c, &o, args.e[i]); + check_multi_expr(c, &o, rhs.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); + if (allow_ok && lhs_count == 2 && rhs.count == 1 && + (o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) { + Type *tuple = make_optional_ok_type(c->allocator, o.type); add_type_and_value(&c->info, o.expr, o.mode, tuple, o.value); Operand val = o; @@ -4922,16 +4918,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint goto error; } - Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); - variables[0] = make_entity_param(c->allocator, NULL, empty_token, t, false, true); - variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true); - - Type *tuple = make_type_tuple(c->allocator); - tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = 2; + add_type_info_type(c, o->type); + add_type_info_type(c, t); - o->type = tuple; - o->mode = Addressing_Value; + o->type = t; + o->mode = Addressing_OptionalOk; } break; case Token_down_cast: { if (o->mode == Addressing_Constant) { diff --git a/src/check_stmt.c b/src/check_stmt.c index 6769ddb40..138e1277e 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -260,6 +260,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { switch (lhs.mode) { case Addressing_Invalid: return NULL; + case Addressing_Variable: break; case Addressing_MapIndex: { @@ -278,6 +279,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) { } } } break; + default: { if (lhs.expr->kind == AstNode_SelectorExpr) { // NOTE(bill): Extra error checks @@ -434,40 +436,34 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { switch (as->op.kind) { case Token_Eq: { // a, b, c = 1, 2, 3; // Multisided - if (as->lhs.count == 0) { + + isize lhs_count = as->lhs.count; + if (lhs_count == 0) { error(as->op, "Missing lhs in assignment statement"); return; } + // TODO(bill): This is a very similar to check_init_variables, should I merge the two some how or just + // leave it? + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); // NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be // an extra allocation - Array(Operand) operands; - array_init_reserve(&operands, c->tmp_allocator, 2 * as->lhs.count); + ArrayOperand operands = {0}; + array_init_reserve(&operands, c->tmp_allocator, 2 * lhs_count); + check_unpack_arguments(c, lhs_count, &operands, as->rhs, true); - for_array(i, as->rhs) { - AstNode *rhs = as->rhs.e[i]; - Operand o = {0}; - check_multi_expr(c, &o, rhs); - if (o.type->kind != Type_Tuple) { - array_add(&operands, o); - } else { - TypeTuple *tuple = &o.type->Tuple; - for (isize j = 0; j < tuple->variable_count; j++) { - o.type = tuple->variables[j]->type; - array_add(&operands, o); - } + isize rhs_count = operands.count; + for_array(i, operands) { + if (operands.e[i].mode == Addressing_Invalid) { + rhs_count--; } } - isize lhs_count = as->lhs.count; - isize rhs_count = operands.count; - - isize operand_count = gb_min(as->lhs.count, operands.count); - for (isize i = 0; i < operand_count; i++) { - AstNode *lhs = as->lhs.e[i]; - check_assignment_variable(c, &operands.e[i], lhs); + isize max = gb_min(lhs_count, rhs_count); + for (isize i = 0; i < max; i++) { + check_assignment_variable(c, &operands.e[i], as->lhs.e[i]); } if (lhs_count != rhs_count) { error_node(as->lhs.e[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); diff --git a/src/checker.c b/src/checker.c index c2fd9e672..9fbf3d36d 100644 --- a/src/checker.c +++ b/src/checker.c @@ -109,18 +109,19 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { #include "types.c" typedef enum AddressingMode { - Addressing_Invalid, // invalid addressing mode - Addressing_NoValue, // no value (void in C) - Addressing_Value, // computed value (rvalue) - Addressing_Immutable, // immutable computed value (const rvalue) - Addressing_Variable, // addressable variable (lvalue) - Addressing_Constant, // constant & type will be a of Type_Basic (stripping Type_Named) - Addressing_Type, // type - Addressing_Builtin, // built in procedure - Addressing_Overload, // overloaded procedure - Addressing_MapIndex, // map index expression - // lhs: acts like a Variable - // ths: acts like a value with an optional boolean part (for existence check) + Addressing_Invalid, // invalid addressing mode + Addressing_NoValue, // no value (void in C) + Addressing_Value, // computed value (rvalue) + Addressing_Immutable, // immutable computed value (const rvalue) + Addressing_Variable, // addressable variable (lvalue) + Addressing_Constant, // constant & type will be a of Type_Basic (stripping Type_Named) + Addressing_Type, // type + Addressing_Builtin, // built in procedure + Addressing_Overload, // overloaded procedure + Addressing_MapIndex, // map index expression - + // lhs: acts like a Variable + // rhs: acts like OptionalOk + Addressing_OptionalOk, // rhs: acts like a value with an optional boolean part (for existence check) } AddressingMode; // Operand is used as an intermediate value whilst checking @@ -2462,13 +2462,19 @@ irValue *ir_emit_down_cast(irProcedure *proc, irValue *value, Type *t) { return ir_emit_conv(proc, head, t); } -irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *tuple) { - GB_ASSERT(tuple->kind == Type_Tuple); +irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, TokenPos pos) { gbAllocator a = proc->module->allocator; Type *src_type = ir_type(value); bool is_ptr = is_type_pointer(src_type); + bool is_tuple = true; + Type *tuple = type; + if (type->kind != Type_Tuple) { + is_tuple = false; + tuple = make_optional_ok_type(a, type); + } + irValue *v = ir_add_local_generated(proc, tuple); if (is_ptr) { @@ -2541,6 +2547,25 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *tuple) { ir_start_block(proc, end_block); } + + if (!is_tuple) { + // NOTE(bill): Panic on invalid conversion + Type *dst_type = tuple->Tuple.variables[0]->type; + + irValue *ok = ir_emit_load(proc, ir_emit_struct_ep(proc, v, 1)); + irValue **args = gb_alloc_array(a, irValue *, 6); + args[0] = ok; + + args[1] = ir_make_const_string(a, pos.file); + args[2] = ir_make_const_int(a, pos.line); + args[3] = ir_make_const_int(a, pos.column); + + args[4] = ir_type_info(proc, src_type); + args[5] = ir_type_info(proc, dst_type); + ir_emit_global_call(proc, "__union_cast_check", args, 6); + + return ir_emit_load(proc, ir_emit_struct_ep(proc, v, 0)); + } return ir_emit_load(proc, v); } @@ -2930,23 +2955,23 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv case_ast_node(ce, CastExpr, expr); Type *type = tv->type; - irValue *expr = ir_build_expr(proc, ce->expr); + irValue *e = ir_build_expr(proc, ce->expr); switch (ce->token.kind) { case Token_cast: ir_emit_comment(proc, str_lit("cast - cast")); - return ir_emit_conv(proc, expr, type); + return ir_emit_conv(proc, e, type); case Token_transmute: ir_emit_comment(proc, str_lit("cast - transmute")); - return ir_emit_transmute(proc, expr, type); + return ir_emit_transmute(proc, e, type); case Token_down_cast: ir_emit_comment(proc, str_lit("cast - down_cast")); - return ir_emit_down_cast(proc, expr, type); + return ir_emit_down_cast(proc, e, type); case Token_union_cast: ir_emit_comment(proc, str_lit("cast - union_cast")); - return ir_emit_union_cast(proc, expr, type); + return ir_emit_union_cast(proc, e, type, ast_node_token(expr).pos); default: GB_PANIC("Unknown cast expression"); @@ -3384,7 +3409,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv args[1] = ir_make_const_int(proc->module->allocator, pos.line); args[2] = ir_make_const_int(proc->module->allocator, pos.column); args[3] = msg; - ir_emit_global_call(proc, "__assert", args, 4); + ir_emit_global_call(proc, "__panic", args, 4); return NULL; } break; |