DoxigAlpha

renderAsm

Function parameters

Parameters

#
r:*Render
asm_node:Ast.full.Asm

Type definitions in this namespace

Types

#

Functions in this namespace

Functions

#

Error sets in this namespace

Error Sets

#

Source

Implementation

#
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
    }

    if (asm_node.ast.items.len == 0) {
        try ais.forcePushIndent(.normal);
        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, .space);
            try renderExpression(r, clobbers, .none);
            ais.popIndent();
            return renderToken(r, asm_node.ast.rparen, space); // rparen
        }

        // asm ("foo")
        try renderExpression(r, asm_node.ast.template, .none);
        ais.popIndent();
        return renderToken(r, asm_node.ast.rparen, space); // rparen
    }

    try ais.forcePushIndent(.normal);
    try renderExpression(r, asm_node.ast.template, .newline);
    ais.setIndentDelta(asm_indent_delta);
    const colon1 = tree.lastToken(asm_node.ast.template) + 1;

    const colon2 = if (asm_node.outputs.len == 0) colon2: {
        try renderToken(r, colon1, .newline); // :
        break :colon2 colon1 + 1;
    } else colon2: {
        try renderToken(r, colon1, .space); // :

        try ais.forcePushIndent(.normal);
        for (asm_node.outputs, 0..) |asm_output, i| {
            if (i + 1 < asm_node.outputs.len) {
                const next_asm_output = asm_node.outputs[i + 1];
                try renderAsmOutput(r, asm_output, .none);

                const comma = tree.firstToken(next_asm_output) - 1;
                try renderToken(r, comma, .newline); // ,
                try renderExtraNewlineToken(r, tree.firstToken(next_asm_output));
            } else if (asm_node.inputs.len == 0 and asm_node.ast.clobbers == .none) {
                try ais.pushSpace(.comma);
                try renderAsmOutput(r, asm_output, .comma);
                ais.popSpace();
                ais.popIndent();
                ais.setIndentDelta(indent_delta);
                ais.popIndent();
                return renderToken(r, asm_node.ast.rparen, space); // rparen
            } else {
                try ais.pushSpace(.comma);
                try renderAsmOutput(r, asm_output, .comma);
                ais.popSpace();
                const comma_or_colon = tree.lastToken(asm_output) + 1;
                ais.popIndent();
                break :colon2 switch (tree.tokenTag(comma_or_colon)) {
                    .comma => comma_or_colon + 1,
                    else => comma_or_colon,
                };
            }
        } else unreachable;
    };

    const colon3 = if (asm_node.inputs.len == 0) colon3: {
        try renderToken(r, colon2, .newline); // :
        break :colon3 colon2 + 1;
    } else colon3: {
        try renderToken(r, colon2, .space); // :
        try ais.forcePushIndent(.normal);
        for (asm_node.inputs, 0..) |asm_input, i| {
            if (i + 1 < asm_node.inputs.len) {
                const next_asm_input = asm_node.inputs[i + 1];
                try renderAsmInput(r, asm_input, .none);

                const first_token = tree.firstToken(next_asm_input);
                try renderToken(r, first_token - 1, .newline); // ,
                try renderExtraNewlineToken(r, first_token);
            } else if (asm_node.ast.clobbers == .none) {
                try ais.pushSpace(.comma);
                try renderAsmInput(r, asm_input, .comma);
                ais.popSpace();
                ais.popIndent();
                ais.setIndentDelta(indent_delta);
                ais.popIndent();
                return renderToken(r, asm_node.ast.rparen, space); // rparen
            } else {
                try ais.pushSpace(.comma);
                try renderAsmInput(r, asm_input, .comma);
                ais.popSpace();
                const comma_or_colon = tree.lastToken(asm_input) + 1;
                ais.popIndent();
                break :colon3 switch (tree.tokenTag(comma_or_colon)) {
                    .comma => comma_or_colon + 1,
                    else => comma_or_colon,
                };
            }
        }
        unreachable;
    };

    try renderToken(r, colon3, .space); // :
    const clobbers = asm_node.ast.clobbers.unwrap().?;
    try renderExpression(r, clobbers, .none);
    ais.setIndentDelta(indent_delta);
    ais.popIndent();
    return renderToken(r, asm_node.ast.rparen, space); // rparen
}