diff options
Diffstat (limited to 'src/check_stmt.cpp')
| -rw-r--r-- | src/check_stmt.cpp | 55 |
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) { |