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.

renderAsm

Render.renderAsm
fn renderAsm(
    r: *Render,
    asm_node: Ast.full.Asm,
    space: Space,
) Error!void

File

lib/std/zig/Ast/Render.zig:2438

Code

fn renderAsm(
    r: *Render,
    asm_node: Ast.full.Asm,
    space: Space,
) Error!void {
    const tree = r.tree;
    const ais = r.ais;

    try renderToken(r, asm_node.ast.asm_token, .space); // asm

    if (asm_node.volatile_token) |volatile_token| {
        try renderToken(r, volatile_token, .space); // volatile
        try renderToken(r, volatile_token + 1, .none); // lparen
    } else {
        try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen
    }

    const render_colons: [3]?Ast.TokenIndex = colons: {
        var colons: [3]Ast.TokenIndex = undefined;
        var render: u2 = 0;

        const rparen = asm_node.ast.rparen;
        filled: {
            colons[0] = tree.lastToken(asm_node.ast.template) + 1;
            if (colons[0] == rparen) break :filled;

            if (asm_node.outputs.len != 0) {
                colons[1] = tree.lastToken(asm_node.outputs[asm_node.outputs.len - 1]) + 1;
                colons[1] += @intFromBool(tree.tokenTag(colons[1]) == .comma);
                render = 1;
            } else {
                colons[1] = colons[0] + 1;
                if (hasComment(tree, colons[0], colons[1])) render = 1;
            }
            if (colons[1] == rparen) break :filled;

            // Next colon is not checked for here since it cannot present without clobbers
            if (asm_node.inputs.len != 0) {
                render = 2;
            } else {
                const colon_or_rparen = colons[1] + 1;
                if (hasComment(tree, colons[1], colon_or_rparen)) render = 2;
            }

            if (asm_node.ast.clobbers.unwrap()) |clobbers| {
                colons[2] = tree.firstToken(clobbers) - 1;
                render = 3;
            }
        }

        var opt_colons: [3]?Ast.TokenIndex = @splat(null);
        for (0..render) |i| opt_colons[i] = colons[i];
        break :colons opt_colons;
    };

    try ais.forcePushIndent(.normal);

    if (asm_node.ast.items.len == 0) {
        if (asm_node.ast.clobbers.unwrap()) |clobbers| {
            // asm ("foo" ::: clobbers)
            try renderExpression(r, asm_node.ast.template, .space);
            // Render the three colons.
            const first_clobber = tree.firstToken(clobbers);
            try renderToken(r, first_clobber - 3, .none);
            try renderToken(r, first_clobber - 2, .none);
            try renderToken(r, first_clobber - 1, .maybe_space);
            try renderExpression(r, clobbers, .none);
            ais.popIndent();
            return renderToken(r, asm_node.ast.rparen, space); // rparen
        }

        if (render_colons[0] == null) {
            // asm ("foo")
            try renderExpression(r, asm_node.ast.template, .none);
            ais.popIndent();
            return renderToken(r, asm_node.ast.rparen, space); // rparen
        }
    }

    try renderExpression(r, asm_node.ast.template, .newline);
    ais.forceLastIndent(); // Might have been dedented by a multiline string literal
    assert(ais.current_line_empty);

    const prev_indent_delta = ais.indent_delta; // May be part of another asm expression
    // so indent_delta can't be unconditionally used
    ais.setIndentDelta(asm_indent_delta);

    rendered: {
        if (render_colons[0]) |colon1| {
            if (asm_node.outputs.len != 0) {
                try renderToken(r, colon1, .space);
                try ais.forcePushIndent(.normal);

                const final = asm_node.outputs.len - 1;
                for (asm_node.outputs[0..final], 0..) |asm_output, i| {
                    try renderAsmOutput(r, asm_output, .none);

                    const next_start = tree.firstToken(asm_node.outputs[i + 1]);
                    try renderToken(r, next_start - 1, .newline); // ,
                    try renderExtraNewlineToken(r, next_start);
                }

                try ais.pushSpace(.comma);
                try renderAsmOutput(r, asm_node.outputs[final], .comma);
                ais.popSpace();
                ais.popIndent();
            } else {
                try renderToken(r, colon1, .newline);
            }
        } else unreachable;

        if (render_colons[1]) |colon2| {
            if (asm_node.inputs.len != 0) {
                try renderToken(r, colon2, .space);
                try ais.forcePushIndent(.normal);

                const final = asm_node.inputs.len - 1;
                for (asm_node.inputs[0..final], 0..) |asm_input, i| {
                    try renderAsmInput(r, asm_input, .none);

                    const next_start = tree.firstToken(asm_node.inputs[i + 1]);
                    try renderToken(r, next_start - 1, .newline); // ,
                    try renderExtraNewlineToken(r, next_start);
                }

                try ais.pushSpace(.comma);
                try renderAsmInput(r, asm_node.inputs[final], .comma);
                ais.popSpace();
                ais.popIndent();
            } else {
                try renderToken(r, colon2, .newline);
            }
        } else break :rendered;

        if (render_colons[2]) |colon3| {
            const clobbers = asm_node.ast.clobbers.unwrap().?;
            try renderToken(r, colon3, .maybe_space);
            try renderExpression(r, clobbers, .none);
            ais.forceLastIndent(); // Might have been dedented by a multiline string literal
        }
    }

    ais.setIndentDelta(prev_indent_delta);
    ais.popIndent();
    return renderToken(r, asm_node.ast.rparen, space); // rparen
}