Translates compound assignment using the equivalent Zig operator if possible.
fn transCompoundAssignSimple(t: *Translator, scope: *Scope, lhs_dummy_opt: ?ZigNode, assign: Node.Binary) TransError!?ZigNode
fn transCompoundAssignSimple(t: *Translator, scope: *Scope, lhs_dummy_opt: ?ZigNode, assign: Node.Binary) TransError!?ZigNode {
const assign_rhs = assign.rhs.get(t.tree);
if (assign_rhs == .cast) return null;
const is_signed = t.signedness(assign.qt) == .signed;
switch (assign_rhs) {
.div_expr, .mod_expr => if (is_signed) return null,
else => {},
}
const lhs_ptr = assign.qt.isPointer(t.comp);
const bin, const op: ZigTag, const cast: enum { none, shift, usize } = switch (assign_rhs) {
.add_expr => |bin| .{
bin,
if (t.typeHasWrappingOverflow(bin.qt)) .add_wrap_assign else .add_assign,
if (lhs_ptr and t.signedness(bin.rhs.qt(t.tree)) == .signed) .usize else .none,
},
.sub_expr => |bin| .{
bin,
if (t.typeHasWrappingOverflow(bin.qt)) .sub_wrap_assign else .sub_assign,
if (lhs_ptr and t.signedness(bin.rhs.qt(t.tree)) == .signed) .usize else .none,
},
.mul_expr => |bin| .{
bin,
if (t.typeHasWrappingOverflow(bin.qt)) .mul_wrap_assign else .mul_assign,
.none,
},
.mod_expr => |bin| .{ bin, .mod_assign, .none },
.div_expr => |bin| .{ bin, .div_assign, .none },
.shl_expr => |bin| .{ bin, .shl_assign, .shift },
.shr_expr => |bin| .{ bin, .shr_assign, .shift },
.bit_and_expr => |bin| .{ bin, .bit_and_assign, .none },
.bit_xor_expr => |bin| .{ bin, .bit_xor_assign, .none },
.bit_or_expr => |bin| .{ bin, .bit_or_assign, .none },
else => unreachable,
};
const lhs_node = blk: {
const old_dummy = t.compound_assign_dummy;
defer t.compound_assign_dummy = old_dummy;
t.compound_assign_dummy = lhs_dummy_opt orelse try t.transExpr(scope, assign.lhs, .used);
break :blk try t.transExpr(scope, bin.lhs, .used);
};
const rhs_node = try t.transExprCoercing(scope, bin.rhs, .used);
const casted_rhs = switch (cast) {
.none => rhs_node,
.shift => try ZigTag.int_cast.create(t.arena, rhs_node),
.usize => try t.usizeCastForWrappingPtrArithmetic(rhs_node),
};
return try t.createBinOpNode(op, lhs_node, casted_rhs);
}