aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-14 16:37:24 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-14 16:37:24 +0000
commit8b5e3428a1e569abf763e63e859754e767e107e7 (patch)
tree302a0cd18b18436feeac7bf50d0d430b0368251a /src
parentd1f65097c48afe6d869949cc5ede76a8b14401a9 (diff)
Optional ok for `union_cast` (similar to map indices)
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.c11
-rw-r--r--src/check_expr.c33
-rw-r--r--src/check_stmt.c40
-rw-r--r--src/checker.c25
-rw-r--r--src/ir.c41
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
diff --git a/src/ir.c b/src/ir.c
index f49f9200e..e6bf588de 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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;