Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

transCompoundAssignSimple

Translates compound assignment using the equivalent Zig operator if possible.

Translator.transCompoundAssignSimple
fn transCompoundAssignSimple(t: *Translator, scope: *Scope, lhs_dummy_opt: ?ZigNode, assign: Node.Binary) TransError!?ZigNode

File

lib/compiler/translate-c/Translator.zig:3024

Code

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);
}