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.

expr

Walk.expr
fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void

File

lib/docs/wasm/Walk.zig:641

Code

fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
    const ast = w.file.get_ast();
    switch (ast.nodeTag(node)) {
        .root => unreachable, // Top-level declaration.
        .test_decl => unreachable, // Top-level declaration.
        .container_field_init => unreachable, // Top-level declaration.
        .container_field_align => unreachable, // Top-level declaration.
        .container_field => unreachable, // Top-level declaration.
        .fn_decl => unreachable, // Top-level declaration.

        .global_var_decl => unreachable, // Handled in `block`.
        .local_var_decl => unreachable, // Handled in `block`.
        .simple_var_decl => unreachable, // Handled in `block`.
        .aligned_var_decl => unreachable, // Handled in `block`.
        .@"defer" => unreachable, // Handled in `block`.
        .@"errdefer" => unreachable, // Handled in `block`.

        .switch_case => unreachable, // Handled in `switchExpr`.
        .switch_case_inline => unreachable, // Handled in `switchExpr`.
        .switch_case_one => unreachable, // Handled in `switchExpr`.
        .switch_case_inline_one => unreachable, // Handled in `switchExpr`.

        .asm_output => unreachable, // Handled in `asmExpr`.
        .asm_input => unreachable, // Handled in `asmExpr`.

        .for_range => unreachable, // Handled in `forExpr`.

        .assign,
        .assign_shl,
        .assign_shl_sat,
        .assign_shr,
        .assign_bit_and,
        .assign_bit_or,
        .assign_bit_xor,
        .assign_div,
        .assign_sub,
        .assign_sub_wrap,
        .assign_sub_sat,
        .assign_mod,
        .assign_add,
        .assign_add_wrap,
        .assign_add_sat,
        .assign_mul,
        .assign_mul_wrap,
        .assign_mul_sat,
        .shl,
        .shr,
        .add,
        .add_wrap,
        .add_sat,
        .sub,
        .sub_wrap,
        .sub_sat,
        .mul,
        .mul_wrap,
        .mul_sat,
        .div,
        .mod,
        .shl_sat,

        .bit_and,
        .bit_or,
        .bit_xor,
        .bang_equal,
        .equal_equal,
        .greater_than,
        .greater_or_equal,
        .less_than,
        .less_or_equal,
        .array_cat,

        .error_union,
        .merge_error_sets,
        .bool_and,
        .bool_or,
        .@"catch",
        .@"orelse",
        .array_type,
        .array_access,
        .switch_range,
        => {
            const lhs, const rhs = ast.nodeData(node).node_and_node;
            try expr(w, scope, parent_decl, lhs);
            try expr(w, scope, parent_decl, rhs);
        },

        .assign_destructure => {
            const full = ast.assignDestructure(node);
            for (full.ast.variables) |variable_node| try expr(w, scope, parent_decl, variable_node);
            _ = try expr(w, scope, parent_decl, full.ast.value_expr);
        },

        .bool_not,
        .bit_not,
        .negation,
        .negation_wrap,
        .deref,
        .address_of,
        .optional_type,
        .@"comptime",
        .@"nosuspend",
        .@"suspend",
        .@"resume",
        .@"try",
        => try expr(w, scope, parent_decl, ast.nodeData(node).node),
        .unwrap_optional,
        .grouped_expression,
        => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
        .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node),

        .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]),
        .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]),

        .identifier => {
            const ident_token = ast.nodeMainToken(node);
            const ident_name = ast.tokenSlice(ident_token);
            if (scope.lookup(ast, ident_name)) |var_node| {
                try w.file.get().ident_decls.put(gpa, ident_token, var_node);
            }
        },
        .field_access => {
            const object_node, const field_ident = ast.nodeData(node).node_and_token;
            try w.file.get().token_parents.put(gpa, field_ident, node);
            // This will populate the left-most field object if it is an
            // identifier, allowing rendering code to piece together the link.
            try expr(w, scope, parent_decl, object_node);
        },

        .string_literal,
        .multiline_string_literal,
        .number_literal,
        .unreachable_literal,
        .enum_literal,
        .error_value,
        .anyframe_literal,
        .@"continue",
        .char_literal,
        .error_set_decl,
        => {},

        .asm_simple,
        .@"asm",
        => {
            const full = ast.fullAsm(node).?;
            for (full.ast.items) |n| {
                // There is a missing call here to expr() for .asm_input and
                // .asm_output nodes.
                _ = n;
            }
            try expr(w, scope, parent_decl, full.ast.template);
        },

        .builtin_call_two,
        .builtin_call_two_comma,
        .builtin_call,
        .builtin_call_comma,
        => {
            var buf: [2]Ast.Node.Index = undefined;
            const params = ast.builtinCallParams(&buf, node).?;
            return builtin_call(w, scope, parent_decl, node, params);
        },

        .call_one,
        .call_one_comma,
        .call,
        .call_comma,
        => {
            var buf: [1]Ast.Node.Index = undefined;
            const full = ast.fullCall(&buf, node).?;
            try expr(w, scope, parent_decl, full.ast.fn_expr);
            for (full.ast.params) |param| {
                try expr(w, scope, parent_decl, param);
            }
        },

        .if_simple,
        .@"if",
        => {
            const full = ast.fullIf(node).?;
            try expr(w, scope, parent_decl, full.ast.cond_expr);
            try expr(w, scope, parent_decl, full.ast.then_expr);
            try maybe_expr(w, scope, parent_decl, full.ast.else_expr);
        },

        .while_simple,
        .while_cont,
        .@"while",
        => {
            try while_expr(w, scope, parent_decl, ast.fullWhile(node).?);
        },

        .for_simple, .@"for" => {
            const full = ast.fullFor(node).?;
            for (full.ast.inputs) |input| {
                if (ast.nodeTag(input) == .for_range) {
                    const start, const end = ast.nodeData(input).node_and_opt_node;
                    try expr(w, scope, parent_decl, start);
                    try maybe_expr(w, scope, parent_decl, end);
                } else {
                    try expr(w, scope, parent_decl, input);
                }
            }
            try expr(w, scope, parent_decl, full.ast.then_expr);
            try maybe_expr(w, scope, parent_decl, full.ast.else_expr);
        },

        .slice => return slice(w, scope, parent_decl, ast.slice(node)),
        .slice_open => return slice(w, scope, parent_decl, ast.sliceOpen(node)),
        .slice_sentinel => return slice(w, scope, parent_decl, ast.sliceSentinel(node)),

        .block_two,
        .block_two_semicolon,
        .block,
        .block_semicolon,
        => {
            var buf: [2]Ast.Node.Index = undefined;
            const statements = ast.blockStatements(&buf, node).?;
            return block(w, scope, parent_decl, statements);
        },

        .ptr_type_aligned,
        .ptr_type_sentinel,
        .ptr_type,
        .ptr_type_bit_range,
        => {
            const full = ast.fullPtrType(node).?;
            try maybe_expr(w, scope, parent_decl, full.ast.align_node);
            try maybe_expr(w, scope, parent_decl, full.ast.addrspace_node);
            try maybe_expr(w, scope, parent_decl, full.ast.sentinel);
            try maybe_expr(w, scope, parent_decl, full.ast.bit_range_start);
            try maybe_expr(w, scope, parent_decl, full.ast.bit_range_end);
            try expr(w, scope, parent_decl, full.ast.child_type);
        },

        .container_decl,
        .container_decl_trailing,
        .container_decl_arg,
        .container_decl_arg_trailing,
        .container_decl_two,
        .container_decl_two_trailing,
        .tagged_union,
        .tagged_union_trailing,
        .tagged_union_enum_tag,
        .tagged_union_enum_tag_trailing,
        .tagged_union_two,
        .tagged_union_two_trailing,
        => {
            var buf: [2]Ast.Node.Index = undefined;
            return struct_decl(w, scope, parent_decl, node, ast.fullContainerDecl(&buf, node).?);
        },

        .array_type_sentinel => {
            const len_expr, const extra_index = ast.nodeData(node).node_and_extra;
            const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
            try expr(w, scope, parent_decl, len_expr);
            try expr(w, scope, parent_decl, extra.elem_type);
            try expr(w, scope, parent_decl, extra.sentinel);
        },
        .@"switch", .switch_comma => {
            const full = ast.fullSwitch(node).?;
            try expr(w, scope, parent_decl, full.ast.condition);
            for (full.ast.cases) |case_node| {
                const case = ast.fullSwitchCase(case_node).?;
                for (case.ast.values) |value_node| {
                    try expr(w, scope, parent_decl, value_node);
                }
                try expr(w, scope, parent_decl, case.ast.target_expr);
            }
        },

        .array_init_one,
        .array_init_one_comma,
        .array_init_dot_two,
        .array_init_dot_two_comma,
        .array_init_dot,
        .array_init_dot_comma,
        .array_init,
        .array_init_comma,
        => {
            var buf: [2]Ast.Node.Index = undefined;
            const full = ast.fullArrayInit(&buf, node).?;
            try maybe_expr(w, scope, parent_decl, full.ast.type_expr);
            for (full.ast.elements) |elem| {
                try expr(w, scope, parent_decl, elem);
            }
        },

        .struct_init_one,
        .struct_init_one_comma,
        .struct_init_dot_two,
        .struct_init_dot_two_comma,
        .struct_init_dot,
        .struct_init_dot_comma,
        .struct_init,
        .struct_init_comma,
        => {
            var buf: [2]Ast.Node.Index = undefined;
            const full = ast.fullStructInit(&buf, node).?;
            try maybe_expr(w, scope, parent_decl, full.ast.type_expr);
            for (full.ast.fields) |field| {
                try expr(w, scope, parent_decl, field);
            }
        },

        .fn_proto_simple,
        .fn_proto_multi,
        .fn_proto_one,
        .fn_proto,
        => {
            var buf: [1]Ast.Node.Index = undefined;
            return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?);
        },
    }
}