aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 0c90e08f0..3266bd780 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1296,9 +1296,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
o->expr = as->lhs[i];
o->mode = Addressing_Value;
} else {
+ ctx->assignment_lhs_hint = unparen_expr(as->lhs[i]);
check_expr(ctx, &lhs_operands[i], as->lhs[i]);
}
}
+ ctx->assignment_lhs_hint = nullptr; // Reset the assignment_lhs_hint
check_assignment_arguments(ctx, lhs_operands, &rhs_operands, as->rhs);
@@ -1310,8 +1312,61 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
}
+ auto lhs_to_ignore = array_make<bool>(ctx->allocator, lhs_count);
+ defer (array_free(&lhs_to_ignore));
+
isize max = gb_min(lhs_count, rhs_count);
+ // NOTE(bill, 2020-05-02): This is an utter hack to get these custom atom operations working
+ // correctly for assignments
for (isize i = 0; i < max; i++) {
+ if (lhs_operands[i].mode == Addressing_AtomOpAssign) {
+ Operand lhs = lhs_operands[i];
+
+ Type *t = base_type(lhs.type);
+ GB_ASSERT(t->kind == Type_Struct);
+ ast_node(ie, IndexExpr, unparen_expr(lhs.expr));
+
+ TypeAtomOpTable *atom_op_table = t->Struct.atom_op_table;
+ GB_ASSERT(atom_op_table->op[TypeAtomOp_index_set] != nullptr);
+ Entity *e = atom_op_table->op[TypeAtomOp_index_set];
+
+ GB_ASSERT(e->identifier != nullptr);
+ Ast *proc_ident = clone_ast(e->identifier);
+ GB_ASSERT(ctx->file != nullptr);
+
+
+ TypeAndValue tv = type_and_value_of_expr(ie->expr);
+ Ast *expr = ie->expr;
+ if (is_type_pointer(tv.type)) {
+ // Okay
+ } else if (tv.mode == Addressing_Variable) {
+ // NOTE(bill): Hack it to take the address instead
+ expr = ast_unary_expr(ctx->file, {Token_And, STR_LIT("&")}, ie->expr);
+ } else {
+ continue;
+ }
+
+ auto args = array_make<Ast *>(heap_allocator(), 3);
+ args[0] = expr;
+ args[1] = ie->index;
+ args[2] = rhs_operands[i].expr;
+
+ Ast *fake_call = ast_call_expr(ctx->file, proc_ident, args, ie->open, ie->close, {});
+ Operand fake_operand = {};
+ fake_operand.expr = lhs.expr;
+ check_expr_base(ctx, &fake_operand, fake_call, nullptr);
+ AtomOpMapEntry entry = {TypeAtomOp_index_set, fake_call};
+ map_set(&ctx->info->atom_op_map, hash_pointer(lhs.expr), entry);
+
+ lhs_to_ignore[i] = true;
+
+ }
+ }
+
+ for (isize i = 0; i < max; i++) {
+ if (lhs_to_ignore[i]) {
+ continue;
+ }
check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i]);
}
if (lhs_count != rhs_count) {