feature. See also
. The project being documented here (as the example) is the Zig library itself.
Walk.expr
fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void
File
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,
.test_decl => unreachable,
.container_field_init => unreachable,
.container_field_align => unreachable,
.container_field => unreachable,
.fn_decl => unreachable,
.global_var_decl => unreachable,
.local_var_decl => unreachable,
.simple_var_decl => unreachable,
.aligned_var_decl => unreachable,
.@"defer" => unreachable,
.@"errdefer" => unreachable,
.switch_case => unreachable,
.switch_case_inline => unreachable,
.switch_case_one => unreachable,
.switch_case_inline_one => unreachable,
.asm_output => unreachable,
.asm_input => unreachable,
.for_range => unreachable,
.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);
// 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| {
// .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).?);
},
}
}