Commit 7a1a924788
Changed files (5)
lib
std
src-self-hosted
lib/std/zig/ast.zig
@@ -471,9 +471,14 @@ pub const Node = struct {
ArrayTypeSentinel,
PtrType,
SliceType,
- /// Not all suffix operations are under this tag. To save memory, some
- /// suffix operations have dedicated Node tags.
- SuffixOp,
+ /// `a[b..c]`
+ Slice,
+ /// `a.*`
+ Deref,
+ /// `a.?`
+ UnwrapOptional,
+ /// `a[b]`
+ ArrayAccess,
/// `T{a, b}`
ArrayInitializer,
/// ArrayInitializer but with `.` instead of a left-hand-side operand.
@@ -601,7 +606,9 @@ pub const Node = struct {
.PtrType => PtrType,
.SliceType => SliceType,
- .SuffixOp => SuffixOp,
+ .Slice => Slice,
+ .Deref, .UnwrapOptional => SimpleSuffixOp,
+ .ArrayAccess => ArrayAccess,
.ArrayInitializer => ArrayInitializer,
.ArrayInitializerDot => ArrayInitializerDot,
@@ -2398,8 +2405,8 @@ pub const Node = struct {
/// Parameter nodes directly follow Call in memory.
pub const Call = struct {
base: Node = Node{ .tag = .Call },
- lhs: *Node,
rtoken: TokenIndex,
+ lhs: *Node,
params_len: NodeIndex,
async_token: ?TokenIndex,
@@ -2450,62 +2457,90 @@ pub const Node = struct {
}
};
- pub const SuffixOp = struct {
- base: Node = Node{ .tag = .SuffixOp },
- op: Op,
+ pub const ArrayAccess = struct {
+ base: Node = Node{ .tag = .ArrayAccess },
+ rtoken: TokenIndex,
lhs: *Node,
+ index_expr: *Node,
+
+ pub fn iterate(self: *const ArrayAccess, index: usize) ?*Node {
+ var i = index;
+
+ if (i < 1) return self.lhs;
+ i -= 1;
+
+ if (i < 1) return self.index_expr;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: *const ArrayAccess) TokenIndex {
+ return self.lhs.firstToken();
+ }
+
+ pub fn lastToken(self: *const ArrayAccess) TokenIndex {
+ return self.rtoken;
+ }
+ };
+
+ pub const SimpleSuffixOp = struct {
+ base: Node,
rtoken: TokenIndex,
+ lhs: *Node,
- pub const Op = union(enum) {
- ArrayAccess: *Node,
- Slice: Slice,
- Deref,
- UnwrapOptional,
+ pub fn iterate(self: *const SimpleSuffixOp, index: usize) ?*Node {
+ var i = index;
- pub const Slice = struct {
- start: *Node,
- end: ?*Node,
- sentinel: ?*Node,
- };
- };
+ if (i < 1) return self.lhs;
+ i -= 1;
- pub fn iterate(self: *const SuffixOp, index: usize) ?*Node {
+ return null;
+ }
+
+ pub fn firstToken(self: *const SimpleSuffixOp) TokenIndex {
+ return self.lhs.firstToken();
+ }
+
+ pub fn lastToken(self: *const SimpleSuffixOp) TokenIndex {
+ return self.rtoken;
+ }
+ };
+
+ pub const Slice = struct {
+ base: Node = Node{ .tag = .Slice },
+ rtoken: TokenIndex,
+ lhs: *Node,
+ start: *Node,
+ end: ?*Node,
+ sentinel: ?*Node,
+
+ pub fn iterate(self: *const Slice, index: usize) ?*Node {
var i = index;
- if (i == 0) return self.lhs;
+ if (i < 1) return self.lhs;
i -= 1;
- switch (self.op) {
- .ArrayAccess => |index_expr| {
- if (i < 1) return index_expr;
- i -= 1;
- },
- .Slice => |range| {
- if (i < 1) return range.start;
- i -= 1;
+ if (i < 1) return self.start;
+ i -= 1;
- if (range.end) |end| {
- if (i < 1) return end;
- i -= 1;
- }
- if (range.sentinel) |sentinel| {
- if (i < 1) return sentinel;
- i -= 1;
- }
- },
- .UnwrapOptional,
- .Deref,
- => {},
+ if (self.end) |end| {
+ if (i < 1) return end;
+ i -= 1;
+ }
+ if (self.sentinel) |sentinel| {
+ if (i < 1) return sentinel;
+ i -= 1;
}
return null;
}
- pub fn firstToken(self: *const SuffixOp) TokenIndex {
+ pub fn firstToken(self: *const Slice) TokenIndex {
return self.lhs.firstToken();
}
- pub fn lastToken(self: *const SuffixOp) TokenIndex {
+ pub fn lastToken(self: *const Slice) TokenIndex {
return self.rtoken;
}
};
lib/std/zig/parse.zig
@@ -1439,58 +1439,7 @@ const Parser = struct {
.ExpectedPrimaryTypeExpr = .{ .token = p.tok_i },
});
- // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards.
- while (try p.parseSuffixOp()) |node| {
- switch (node.tag) {
- .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
- .Catch => node.castTag(.Catch).?.lhs = res,
-
- .Add,
- .AddWrap,
- .ArrayCat,
- .ArrayMult,
- .Assign,
- .AssignBitAnd,
- .AssignBitOr,
- .AssignBitShiftLeft,
- .AssignBitShiftRight,
- .AssignBitXor,
- .AssignDiv,
- .AssignSub,
- .AssignSubWrap,
- .AssignMod,
- .AssignAdd,
- .AssignAddWrap,
- .AssignMul,
- .AssignMulWrap,
- .BangEqual,
- .BitAnd,
- .BitOr,
- .BitShiftLeft,
- .BitShiftRight,
- .BitXor,
- .BoolAnd,
- .BoolOr,
- .Div,
- .EqualEqual,
- .ErrorUnion,
- .GreaterOrEqual,
- .GreaterThan,
- .LessOrEqual,
- .LessThan,
- .MergeErrorSets,
- .Mod,
- .Mul,
- .MulWrap,
- .Period,
- .Range,
- .Sub,
- .SubWrap,
- .OrElse,
- => node.cast(Node.SimpleInfixOp).?.lhs = res,
-
- else => unreachable,
- }
+ while (try p.parseSuffixOp(res)) |node| {
res = node;
}
@@ -1516,57 +1465,7 @@ const Parser = struct {
var res = expr;
while (true) {
- // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards.
- if (try p.parseSuffixOp()) |node| {
- switch (node.tag) {
- .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
- .Catch => node.castTag(.Catch).?.lhs = res,
-
- .Add,
- .AddWrap,
- .ArrayCat,
- .ArrayMult,
- .Assign,
- .AssignBitAnd,
- .AssignBitOr,
- .AssignBitShiftLeft,
- .AssignBitShiftRight,
- .AssignBitXor,
- .AssignDiv,
- .AssignSub,
- .AssignSubWrap,
- .AssignMod,
- .AssignAdd,
- .AssignAddWrap,
- .AssignMul,
- .AssignMulWrap,
- .BangEqual,
- .BitAnd,
- .BitOr,
- .BitShiftLeft,
- .BitShiftRight,
- .BitXor,
- .BoolAnd,
- .BoolOr,
- .Div,
- .EqualEqual,
- .ErrorUnion,
- .GreaterOrEqual,
- .GreaterThan,
- .LessOrEqual,
- .LessThan,
- .MergeErrorSets,
- .Mod,
- .Mul,
- .MulWrap,
- .Period,
- .Range,
- .Sub,
- .SubWrap,
- .OrElse,
- => node.cast(Node.SimpleInfixOp).?.lhs = res,
- else => unreachable,
- }
+ if (try p.parseSuffixOp(res)) |node| {
res = node;
continue;
}
@@ -2733,78 +2632,77 @@ const Parser = struct {
/// / DOT IDENTIFIER
/// / DOTASTERISK
/// / DOTQUESTIONMARK
- fn parseSuffixOp(p: *Parser) !?*Node {
- const OpAndToken = struct {
- op: Node.SuffixOp.Op,
- token: TokenIndex,
- };
- const op_and_token: OpAndToken = blk: {
- if (p.eatToken(.LBracket)) |_| {
- const index_expr = try p.expectNode(parseExpr, .{
- .ExpectedExpr = .{ .token = p.tok_i },
- });
-
- if (p.eatToken(.Ellipsis2) != null) {
- const end_expr = try p.parseExpr();
- const sentinel: ?*Node = if (p.eatToken(.Colon) != null)
- try p.parseExpr()
- else
- null;
- break :blk .{
- .op = .{
- .Slice = .{
- .start = index_expr,
- .end = end_expr,
- .sentinel = sentinel,
- },
- },
- .token = try p.expectToken(.RBracket),
- };
- }
+ fn parseSuffixOp(p: *Parser, lhs: *Node) !?*Node {
+ if (p.eatToken(.LBracket)) |_| {
+ const index_expr = try p.expectNode(parseExpr, .{
+ .ExpectedExpr = .{ .token = p.tok_i },
+ });
- break :blk .{
- .op = .{ .ArrayAccess = index_expr },
- .token = try p.expectToken(.RBracket),
+ if (p.eatToken(.Ellipsis2) != null) {
+ const end_expr = try p.parseExpr();
+ const sentinel: ?*Node = if (p.eatToken(.Colon) != null)
+ try p.parseExpr()
+ else
+ null;
+ const rtoken = try p.expectToken(.RBracket);
+ const node = try p.arena.allocator.create(Node.Slice);
+ node.* = .{
+ .lhs = lhs,
+ .rtoken = rtoken,
+ .start = index_expr,
+ .end = end_expr,
+ .sentinel = sentinel,
};
+ return &node.base;
}
- if (p.eatToken(.PeriodAsterisk)) |period_asterisk| {
- break :blk .{ .op = .Deref, .token = period_asterisk };
- }
+ const rtoken = try p.expectToken(.RBracket);
+ const node = try p.arena.allocator.create(Node.ArrayAccess);
+ node.* = .{
+ .lhs = lhs,
+ .rtoken = rtoken,
+ .index_expr = index_expr,
+ };
+ return &node.base;
+ }
- if (p.eatToken(.Period)) |period| {
- if (try p.parseIdentifier()) |identifier| {
- // TODO: It's a bit weird to return a SimpleInfixOp from the SuffixOp parser.
- // Should there be an Node.SuffixOp.FieldAccess variant? Or should
- // this grammar rule be altered?
- const node = try p.arena.allocator.create(Node.SimpleInfixOp);
- node.* = .{
- .base = Node{ .tag = .Period },
- .op_token = period,
- .lhs = undefined, // set by caller
- .rhs = identifier,
- };
- return &node.base;
- }
- if (p.eatToken(.QuestionMark)) |question_mark| {
- break :blk .{ .op = .UnwrapOptional, .token = question_mark };
- }
- try p.errors.append(p.gpa, .{
- .ExpectedSuffixOp = .{ .token = p.tok_i },
- });
- return null;
- }
+ if (p.eatToken(.PeriodAsterisk)) |period_asterisk| {
+ const node = try p.arena.allocator.create(Node.SimpleSuffixOp);
+ node.* = .{
+ .base = .{ .tag = .Deref },
+ .lhs = lhs,
+ .rtoken = period_asterisk,
+ };
+ return &node.base;
+ }
+ if (p.eatToken(.Period)) |period| {
+ if (try p.parseIdentifier()) |identifier| {
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
+ node.* = .{
+ .base = Node{ .tag = .Period },
+ .op_token = period,
+ .lhs = lhs,
+ .rhs = identifier,
+ };
+ return &node.base;
+ }
+ if (p.eatToken(.QuestionMark)) |question_mark| {
+ const node = try p.arena.allocator.create(Node.SimpleSuffixOp);
+ node.* = .{
+ .base = .{ .tag = .UnwrapOptional },
+ .lhs = lhs,
+ .rtoken = question_mark,
+ };
+ return &node.base;
+ }
+ try p.errors.append(p.gpa, .{
+ .ExpectedSuffixOp = .{ .token = p.tok_i },
+ });
return null;
- };
+ }
- const node = try p.arena.allocator.create(Node.SuffixOp);
- node.* = .{
- .lhs = undefined, // set by caller
- .op = op_and_token.op,
- .rtoken = op_and_token.token,
- };
- return &node.base;
+ return null;
}
/// FnCallArguments <- LPAREN ExprList RPAREN
lib/std/zig/render.zig
@@ -1044,68 +1044,67 @@ fn renderExpression(
return renderToken(tree, stream, call.rtoken, indent, start_col, space);
},
- .SuffixOp => {
- const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base);
-
- switch (suffix_op.op) {
- .ArrayAccess => |index_expr| {
- const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
- const rbracket = tree.nextToken(index_expr.lastToken());
-
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
- try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
-
- const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;
- const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;
- const new_indent = if (ends_with_comment) indent + indent_delta else indent;
- const new_space = if (ends_with_comment) Space.Newline else Space.None;
- try renderExpression(allocator, stream, tree, new_indent, start_col, index_expr, new_space);
- if (starts_with_comment) {
- try stream.writeByte('\n');
- }
- if (ends_with_comment or starts_with_comment) {
- try stream.writeByteNTimes(' ', indent);
- }
- return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
- },
+ .ArrayAccess => {
+ const suffix_op = base.castTag(.ArrayAccess).?;
- .Deref => {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
- return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
- },
+ const lbracket = tree.nextToken(suffix_op.lhs.lastToken());
+ const rbracket = tree.nextToken(suffix_op.index_expr.lastToken());
- .UnwrapOptional => {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
- try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
- return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
- },
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
+
+ const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment;
+ const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment;
+ const new_indent = if (ends_with_comment) indent + indent_delta else indent;
+ const new_space = if (ends_with_comment) Space.Newline else Space.None;
+ try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.index_expr, new_space);
+ if (starts_with_comment) {
+ try stream.writeByte('\n');
+ }
+ if (ends_with_comment or starts_with_comment) {
+ try stream.writeByteNTimes(' ', indent);
+ }
+ return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
+ },
+ .Slice => {
+ const suffix_op = base.castTag(.Slice).?;
- .Slice => |range| {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
- const lbracket = tree.prevToken(range.start.firstToken());
- const dotdot = tree.nextToken(range.start.lastToken());
+ const lbracket = tree.prevToken(suffix_op.start.firstToken());
+ const dotdot = tree.nextToken(suffix_op.start.lastToken());
- const after_start_space_bool = nodeCausesSliceOpSpace(range.start) or
- (if (range.end) |end| nodeCausesSliceOpSpace(end) else false);
- const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
- const after_op_space = if (range.end != null) after_start_space else Space.None;
+ const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
+ (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
+ const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
+ const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
- try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
- try renderExpression(allocator, stream, tree, indent, start_col, range.start, after_start_space);
- try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // ..
- if (range.end) |end| {
- const after_end_space = if (range.sentinel != null) Space.Space else Space.None;
- try renderExpression(allocator, stream, tree, indent, start_col, end, after_end_space);
- }
- if (range.sentinel) |sentinel| {
- const colon = tree.prevToken(sentinel.firstToken());
- try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
- try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None);
- }
- return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
- },
+ try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.start, after_start_space);
+ try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // ..
+ if (suffix_op.end) |end| {
+ const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
+ try renderExpression(allocator, stream, tree, indent, start_col, end, after_end_space);
}
+ if (suffix_op.sentinel) |sentinel| {
+ const colon = tree.prevToken(sentinel.firstToken());
+ try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
+ try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None);
+ }
+ return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
+ },
+ .Deref => {
+ const suffix_op = base.castTag(.Deref).?;
+
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
+ },
+ .UnwrapOptional => {
+ const suffix_op = base.castTag(.UnwrapOptional).?;
+
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
+ return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
},
.ControlFlowExpression => {
src-self-hosted/astgen.zig
@@ -34,7 +34,7 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst {
.LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt),
.LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte),
.Period => return field(mod, scope, node.castTag(.Period).?),
- .SuffixOp => return suffixOp(mod, scope, node.castTag(.SuffixOp).?),
+ .Deref => return deref(mod, scope, node.castTag(.Deref).?),
.BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?),
else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),
}
@@ -73,32 +73,41 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop
if (node.getTrailer("align_node")) |align_node| {
return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{});
}
- if (node.getTrailer("type_node")) |type_node| {
- return mod.failNode(scope, type_node, "TODO implement typed locals", .{});
- }
const tree = scope.tree();
switch (tree.token_ids[node.mut_token]) {
- .Keyword_const => {},
+ .Keyword_const => {
+ if (node.getTrailer("type_node")) |type_node| {
+ return mod.failNode(scope, type_node, "TODO implement typed const locals", .{});
+ }
+ // Depending on the type of AST the initialization expression is, we may need an lvalue
+ // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
+ // the variable, no memory location needed.
+ const init_node = node.getTrailer("init_node").?;
+ if (nodeMayNeedMemoryLocation(init_node)) {
+ return mod.failNode(scope, init_node, "TODO implement result locations", .{});
+ }
+ const init_inst = try expr(mod, scope, init_node);
+ const ident_name = try identifierTokenString(mod, scope, node.name_token);
+ return Scope.LocalVar{
+ .parent = scope,
+ .gen_zir = scope.getGenZIR(),
+ .name = ident_name,
+ .inst = init_inst,
+ };
+ },
.Keyword_var => {
- return mod.failTok(scope, node.mut_token, "TODO implement mutable locals", .{});
+ return mod.failNode(scope, &node.base, "TODO implement local vars", .{});
+ //const src = tree.token_locs[node.name_token].start;
+ //const alloc = mod.addZIRInst(scope, src, zir.Inst.Alloc, .{}, .{});
+ //if (node.getTrailer("type_node")) |type_node| {
+ // const type_inst = try expr(mod, scope, type_node);
+ // return mod.failNode(scope, type_node, "TODO implement typed var locals", .{});
+ //} else {
+ // return mod.failTok(scope, node.mut_token, "TODO implement mutable type-inferred locals", .{});
+ //}
},
else => unreachable,
}
- // Depending on the type of AST the initialization expression is, we may need an lvalue
- // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
- // the variable, no memory location needed.
- const init_node = node.getTrailer("init_node").?;
- if (nodeMayNeedMemoryLocation(init_node)) {
- return mod.failNode(scope, init_node, "TODO implement result locations", .{});
- }
- const init_inst = try expr(mod, scope, init_node);
- const ident_name = try identifierTokenString(mod, scope, node.name_token);
- return Scope.LocalVar{
- .parent = scope,
- .gen_zir = scope.getGenZIR(),
- .name = ident_name,
- .inst = init_inst,
- };
}
fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
@@ -163,18 +172,13 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!
return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{});
}
-fn suffixOp(mod: *Module, scope: *Scope, node: *ast.Node.SuffixOp) InnerError!*zir.Inst {
- switch (node.op) {
- .Deref => {
- const tree = scope.tree();
- const src = tree.token_locs[node.rtoken].start;
+fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
+ const tree = scope.tree();
+ const src = tree.token_locs[node.rtoken].start;
- const lhs = try expr(mod, scope, node.lhs);
+ const lhs = try expr(mod, scope, node.lhs);
- return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{});
- },
- else => return mod.failNode(scope, &node.base, "TODO implement astGenExpr for suffixOp {}", .{node.op}),
- }
+ return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{});
}
fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
@@ -672,6 +676,9 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
.Period,
.Sub,
.SubWrap,
+ .Slice,
+ .Deref,
+ .ArrayAccess,
=> return false,
// Forward the question to a sub-expression.
@@ -682,6 +689,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
.OrElse => node = node.castTag(.OrElse).?.rhs,
.Comptime => node = node.castTag(.Comptime).?.expr,
.Nosuspend => node = node.castTag(.Nosuspend).?.expr,
+ .UnwrapOptional => node = node.castTag(.UnwrapOptional).?.lhs,
// True because these are exactly the expressions we need memory locations for.
.ArrayInitializer,
@@ -697,7 +705,6 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
.Switch,
.Call,
.BuiltinCall, // TODO some of these can return false
- .SuffixOp, // TODO this should be split up
=> return true,
// Depending on AST properties, they may need memory locations.
src-self-hosted/translate_c.zig
@@ -2962,9 +2962,9 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS
cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value);
cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
node.rtoken = try appendToken(rp.c, .RBrace, "]");
- node.op.ArrayAccess = &cast_node.base;
+ node.index_expr = &cast_node.base;
} else {
- node.op.ArrayAccess = try transExpr(rp, scope, subscr_expr, .used, .r_value);
+ node.index_expr = try transExpr(rp, scope, subscr_expr, .used, .r_value);
node.rtoken = try appendToken(rp.c, .RBrace, "]");
}
return maybeSuppressResult(rp, scope, result_used, &node.base);
@@ -4405,9 +4405,9 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
_ = try appendToken(c, .Period, ".");
const qm = try appendToken(c, .QuestionMark, "?");
- const node = try c.arena.create(ast.Node.SuffixOp);
+ const node = try c.arena.create(ast.Node.SimpleSuffixOp);
node.* = .{
- .op = .UnwrapOptional,
+ .base = .{ .tag = .UnwrapOptional },
.lhs = wrapped,
.rtoken = qm,
};
@@ -4567,23 +4567,21 @@ fn transCreateNodeShiftOp(
}
fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
- const node = try c.arena.create(ast.Node.SuffixOp);
+ const node = try c.arena.create(ast.Node.SimpleSuffixOp);
node.* = .{
+ .base = .{ .tag = .Deref },
.lhs = lhs,
- .op = .Deref,
.rtoken = try appendToken(c, .PeriodAsterisk, ".*"),
};
return &node.base;
}
-fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.SuffixOp {
+fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAccess {
_ = try appendToken(c, .LBrace, "[");
- const node = try c.arena.create(ast.Node.SuffixOp);
+ const node = try c.arena.create(ast.Node.ArrayAccess);
node.* = .{
.lhs = lhs,
- .op = .{
- .ArrayAccess = undefined,
- },
+ .index_expr = undefined,
.rtoken = undefined,
};
return node;
@@ -6010,7 +6008,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
},
.LBracket => {
const arr_node = try transCreateNodeArrayAccess(c, node);
- arr_node.op.ArrayAccess = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
+ arr_node.index_expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
arr_node.rtoken = try appendToken(c, .RBracket, "]");
node = &arr_node.base;
if (it.next().?.id != .RBracket) {
@@ -6099,7 +6097,6 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
};
mem.copy(*ast.Node, tuple_node.list(), init_vals.items);
-
//(@import("std").mem.zeroInit(T, .{x}))
const import_fn_call = try c.createBuiltinCall("@import", 1);
const std_node = try transCreateNodeStringLiteral(c, "\"std\"");