Commit af12596e8d
Changed files (6)
lib
std
src-self-hosted
lib/std/zig/ast.zig
@@ -408,8 +408,54 @@ pub const Node = struct {
VarDecl,
Defer,
- // Operators
- InfixOp,
+ // Infix operators
+ Catch,
+
+ // SimpleInfixOp
+ 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,
+ UnwrapOptional,
+
+ // SimplePrefixOp
AddressOf,
Await,
BitNot,
@@ -419,6 +465,7 @@ pub const Node = struct {
NegationWrap,
Resume,
Try,
+
ArrayType,
/// ArrayType but has a sentinel node.
ArrayTypeSentinel,
@@ -492,7 +539,51 @@ pub const Node = struct {
.TestDecl => TestDecl,
.VarDecl => VarDecl,
.Defer => Defer,
- .InfixOp => InfixOp,
+ .Catch => Catch,
+
+ .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,
+ .UnwrapOptional,
+ => SimpleInfixOp,
.AddressOf,
.Await,
@@ -507,13 +598,17 @@ pub const Node = struct {
.ArrayType => ArrayType,
.ArrayTypeSentinel => ArrayTypeSentinel,
+
.PtrType => PtrType,
.SliceType => SliceType,
.SuffixOp => SuffixOp,
+
.ArrayInitializer => ArrayInitializer,
.ArrayInitializerDot => ArrayInitializerDot,
+
.StructInitializer => StructInitializer,
.StructInitializerDot => StructInitializerDot,
+
.Call => Call,
.Switch => Switch,
.While => While,
@@ -1859,117 +1954,22 @@ pub const Node = struct {
}
};
- /// TODO split up and make every op its own AST Node tag
- pub const InfixOp = struct {
- base: Node = Node{ .tag = .InfixOp },
+ pub const Catch = struct {
+ base: Node = Node{ .tag = .Catch },
op_token: TokenIndex,
lhs: *Node,
- op: Op,
rhs: *Node,
+ payload: ?*Node,
- pub const Op = union(enum) {
- 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,
- Catch: ?*Node,
- Div,
- EqualEqual,
- ErrorUnion,
- GreaterOrEqual,
- GreaterThan,
- LessOrEqual,
- LessThan,
- MergeErrorSets,
- Mod,
- Mul,
- MulWrap,
- Period,
- Range,
- Sub,
- SubWrap,
- UnwrapOptional,
- };
-
- pub fn iterate(self: *const InfixOp, index: usize) ?*Node {
+ pub fn iterate(self: *const Catch, index: usize) ?*Node {
var i = index;
if (i < 1) return self.lhs;
i -= 1;
- switch (self.op) {
- .Catch => |maybe_payload| {
- if (maybe_payload) |payload| {
- if (i < 1) return payload;
- i -= 1;
- }
- },
-
- .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,
- .UnwrapOptional,
- => {},
+ if (self.payload) |payload| {
+ if (i < 1) return payload;
+ i -= 1;
}
if (i < 1) return self.rhs;
@@ -1978,11 +1978,38 @@ pub const Node = struct {
return null;
}
- pub fn firstToken(self: *const InfixOp) TokenIndex {
+ pub fn firstToken(self: *const Catch) TokenIndex {
+ return self.lhs.firstToken();
+ }
+
+ pub fn lastToken(self: *const Catch) TokenIndex {
+ return self.rhs.lastToken();
+ }
+ };
+
+ pub const SimpleInfixOp = struct {
+ base: Node,
+ op_token: TokenIndex,
+ lhs: *Node,
+ rhs: *Node,
+
+ pub fn iterate(self: *const SimpleInfixOp, index: usize) ?*Node {
+ var i = index;
+
+ if (i < 1) return self.lhs;
+ i -= 1;
+
+ if (i < 1) return self.rhs;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: *const SimpleInfixOp) TokenIndex {
return self.lhs.firstToken();
}
- pub fn lastToken(self: *const InfixOp) TokenIndex {
+ pub fn lastToken(self: *const SimpleInfixOp) TokenIndex {
return self.rhs.lastToken();
}
};
lib/std/zig/parse.zig
@@ -1015,7 +1015,7 @@ const Parser = struct {
/// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
fn parseBoolOrExpr(p: *Parser) !?*Node {
return p.parseBinOpExpr(
- SimpleBinOpParseFn(.Keyword_or, Node.InfixOp.Op.BoolOr),
+ SimpleBinOpParseFn(.Keyword_or, .BoolOr),
parseBoolAndExpr,
.Infinitely,
);
@@ -1405,8 +1405,8 @@ const Parser = struct {
fn parseErrorUnionExpr(p: *Parser) !?*Node {
const suffix_expr = (try p.parseSuffixExpr()) orelse return null;
- if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(p)) |node| {
- const error_union = node.cast(Node.InfixOp).?;
+ if (try SimpleBinOpParseFn(.Bang, .ErrorUnion)(p)) |node| {
+ const error_union = node.castTag(.ErrorUnion).?;
const type_expr = try p.expectNode(parseTypeExpr, .{
.ExpectedTypeExpr = .{ .token = p.tok_i },
});
@@ -1439,10 +1439,56 @@ 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,
- .InfixOp => node.cast(Node.InfixOp).?.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,
+ .UnwrapOptional,
+ => node.cast(Node.SimpleInfixOp).?.lhs = res,
+
else => unreachable,
}
res = node;
@@ -1470,10 +1516,55 @@ 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,
- .InfixOp => node.cast(Node.InfixOp).?.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,
+ .UnwrapOptional,
+ => node.cast(Node.SimpleInfixOp).?.lhs = res,
else => unreachable,
}
res = node;
@@ -1560,11 +1651,11 @@ const Parser = struct {
const global_error_set = try p.createLiteral(Node.ErrorType, token);
if (period == null or identifier == null) return global_error_set;
- const node = try p.arena.allocator.create(Node.InfixOp);
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
+ .base = Node{ .tag = .Period },
.op_token = period.?,
.lhs = global_error_set,
- .op = .Period,
.rhs = identifier.?,
};
return &node.base;
@@ -2237,11 +2328,11 @@ const Parser = struct {
.ExpectedExpr = .{ .token = p.tok_i },
});
- const node = try p.arena.allocator.create(Node.InfixOp);
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
+ .base = Node{ .tag = .Range },
.op_token = token,
.lhs = expr,
- .op = .Range,
.rhs = range_end,
};
return &node.base;
@@ -2266,7 +2357,7 @@ const Parser = struct {
/// / EQUAL
fn parseAssignOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.AsteriskEqual => .AssignMul,
.SlashEqual => .AssignDiv,
.PercentEqual => .AssignMod,
@@ -2287,11 +2378,11 @@ const Parser = struct {
},
};
- const node = try p.arena.allocator.create(Node.InfixOp);
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
+ .base = .{ .tag = op },
.op_token = token,
.lhs = undefined, // set by caller
- .op = op,
.rhs = undefined, // set by caller
};
return &node.base;
@@ -2306,7 +2397,7 @@ const Parser = struct {
/// / RARROWEQUAL
fn parseCompareOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.EqualEqual => .EqualEqual,
.BangEqual => .BangEqual,
.AngleBracketLeft => .LessThan,
@@ -2330,12 +2421,22 @@ const Parser = struct {
/// / KEYWORD_catch Payload?
fn parseBitwiseOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.Ampersand => .BitAnd,
.Caret => .BitXor,
.Pipe => .BitOr,
.Keyword_orelse => .UnwrapOptional,
- .Keyword_catch => .{ .Catch = try p.parsePayload() },
+ .Keyword_catch => {
+ const payload = try p.parsePayload();
+ const node = try p.arena.allocator.create(Node.Catch);
+ node.* = .{
+ .op_token = token,
+ .lhs = undefined, // set by caller
+ .rhs = undefined, // set by caller
+ .payload = payload,
+ };
+ return &node.base;
+ },
else => {
p.putBackToken(token);
return null;
@@ -2350,7 +2451,7 @@ const Parser = struct {
/// / RARROW2
fn parseBitShiftOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.AngleBracketAngleBracketLeft => .BitShiftLeft,
.AngleBracketAngleBracketRight => .BitShiftRight,
else => {
@@ -2370,7 +2471,7 @@ const Parser = struct {
/// / MINUSPERCENT
fn parseAdditionOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.Plus => .Add,
.Minus => .Sub,
.PlusPlus => .ArrayCat,
@@ -2394,7 +2495,7 @@ const Parser = struct {
/// / ASTERISKPERCENT
fn parseMultiplyOp(p: *Parser) !?*Node {
const token = p.nextToken();
- const op: Node.InfixOp.Op = switch (p.token_ids[token]) {
+ const op: Node.Tag = switch (p.token_ids[token]) {
.PipePipe => .MergeErrorSets,
.Asterisk => .Mul,
.Slash => .Div,
@@ -2673,14 +2774,14 @@ const Parser = struct {
if (p.eatToken(.Period)) |period| {
if (try p.parseIdentifier()) |identifier| {
- // TODO: It's a bit weird to return an InfixOp from the SuffixOp parser.
+ // 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.InfixOp);
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
+ .base = Node{ .tag = .Period },
.op_token = period,
.lhs = undefined, // set by caller
- .op = .Period,
.rhs = identifier,
};
return &node.base;
@@ -2987,7 +3088,7 @@ const Parser = struct {
}.parse;
}
- fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) NodeParseFn {
+ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.Tag) NodeParseFn {
return struct {
pub fn parse(p: *Parser) Error!?*Node {
const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) {
@@ -3001,11 +3102,11 @@ const Parser = struct {
else => return null,
} else p.eatToken(token) orelse return null;
- const node = try p.arena.allocator.create(Node.InfixOp);
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
+ .base = .{ .tag = op },
.op_token = op_token,
.lhs = undefined, // set by caller
- .op = op,
.rhs = undefined, // set by caller
};
return &node.base;
@@ -3350,9 +3451,13 @@ const Parser = struct {
const left = res;
res = node;
- const op = node.cast(Node.InfixOp).?;
- op.*.lhs = left;
- op.*.rhs = right;
+ if (node.castTag(.Catch)) |op| {
+ op.lhs = left;
+ op.rhs = right;
+ } else if (node.cast(Node.SimpleInfixOp)) |op| {
+ op.lhs = left;
+ op.rhs = right;
+ }
switch (chain) {
.Once => break,
@@ -3363,12 +3468,12 @@ const Parser = struct {
return res;
}
- fn createInfixOp(p: *Parser, index: TokenIndex, op: Node.InfixOp.Op) !*Node {
- const node = try p.arena.allocator.create(Node.InfixOp);
+ fn createInfixOp(p: *Parser, op_token: TokenIndex, tag: Node.Tag) !*Node {
+ const node = try p.arena.allocator.create(Node.SimpleInfixOp);
node.* = .{
- .op_token = index,
+ .base = Node{ .tag = tag },
+ .op_token = op_token,
.lhs = undefined, // set by caller
- .op = op,
.rhs = undefined, // set by caller
};
return &node.base;
lib/std/zig/render.zig
@@ -436,13 +436,10 @@ fn renderExpression(
}
},
- .InfixOp => {
- const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
+ .Catch => {
+ const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
- const op_space = switch (infix_op_node.op) {
- ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
- else => Space.Space,
- };
+ const op_space = Space.Space;
try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
const after_op_space = blk: {
@@ -458,11 +455,75 @@ fn renderExpression(
start_col.* = indent + indent_delta;
}
- switch (infix_op_node.op) {
- ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {
- try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
- },
- else => {},
+ if (infix_op_node.payload) |payload| {
+ try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
+ }
+
+ return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
+ },
+
+ .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,
+ .UnwrapOptional,
+ => {
+ const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
+
+ const op_space = switch (base.tag) {
+ .Period, .ErrorUnion, .Range => Space.None,
+ else => Space.Space,
+ };
+ try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
+
+ const after_op_space = blk: {
+ const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token));
+ break :blk if (loc.line == 0) op_space else Space.Newline;
+ };
+
+ try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space);
+ if (after_op_space == Space.Newline and
+ tree.token_ids[tree.nextToken(infix_op_node.op_token)] != .MultilineStringLiteralLine)
+ {
+ try stream.writeByteNTimes(' ', indent + indent_delta);
+ start_col.* = indent + indent_delta;
}
return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
@@ -2553,10 +2614,52 @@ fn nodeIsBlock(base: *const ast.Node) bool {
}
fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
- const infix_op = base.cast(ast.Node.InfixOp) orelse return false;
- return switch (infix_op.op) {
- ast.Node.InfixOp.Op.Period => false,
- else => true,
+ return switch (base.tag) {
+ .Catch,
+ .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,
+ .Range,
+ .Sub,
+ .SubWrap,
+ .UnwrapOptional,
+ => true,
+
+ else => false,
};
}
src-self-hosted/astgen.zig
@@ -12,22 +12,29 @@ const Scope = Module.Scope;
const InnerError = Module.InnerError;
/// Turn Zig AST into untyped ZIR istructions.
-pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {
- switch (ast_node.tag) {
+pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst {
+ switch (node.tag) {
.VarDecl => unreachable, // Handled in `blockExpr`.
- .Identifier => return identifier(mod, scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)),
- .Asm => return assembly(mod, scope, @fieldParentPtr(ast.Node.Asm, "base", ast_node)),
- .StringLiteral => return stringLiteral(mod, scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)),
- .IntegerLiteral => return integerLiteral(mod, scope, @fieldParentPtr(ast.Node.IntegerLiteral, "base", ast_node)),
- .BuiltinCall => return builtinCall(mod, scope, @fieldParentPtr(ast.Node.BuiltinCall, "base", ast_node)),
- .Call => return callExpr(mod, scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)),
- .Unreachable => return unreach(mod, scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),
- .ControlFlowExpression => return controlFlowExpr(mod, scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
- .If => return ifExpr(mod, scope, @fieldParentPtr(ast.Node.If, "base", ast_node)),
- .InfixOp => return infixOp(mod, scope, @fieldParentPtr(ast.Node.InfixOp, "base", ast_node)),
- .BoolNot => return boolNot(mod, scope, @fieldParentPtr(ast.Node.SimplePrefixOp, "base", ast_node)),
- else => return mod.failNode(scope, ast_node, "TODO implement astgen.Expr for {}", .{@tagName(ast_node.tag)}),
+ .Identifier => return identifier(mod, scope, node.castTag(.Identifier).?),
+ .Asm => return assembly(mod, scope, node.castTag(.Asm).?),
+ .StringLiteral => return stringLiteral(mod, scope, node.castTag(.StringLiteral).?),
+ .IntegerLiteral => return integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?),
+ .BuiltinCall => return builtinCall(mod, scope, node.castTag(.BuiltinCall).?),
+ .Call => return callExpr(mod, scope, node.castTag(.Call).?),
+ .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),
+ .ControlFlowExpression => return controlFlowExpr(mod, scope, node.castTag(.ControlFlowExpression).?),
+ .If => return ifExpr(mod, scope, node.castTag(.If).?),
+ .Assign => return assign(mod, scope, node.castTag(.Assign).?),
+ .Add => return add(mod, scope, node.castTag(.Add).?),
+ .BangEqual => return cmp(mod, scope, node.castTag(.BangEqual).?, .neq),
+ .EqualEqual => return cmp(mod, scope, node.castTag(.EqualEqual).?, .eq),
+ .GreaterThan => return cmp(mod, scope, node.castTag(.GreaterThan).?, .gt),
+ .GreaterOrEqual => return cmp(mod, scope, node.castTag(.GreaterOrEqual).?, .gte),
+ .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt),
+ .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte),
+ .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?),
+ else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),
}
}
@@ -57,6 +64,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
}
fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar {
+ // TODO implement detection of shadowing
if (node.getTrailer("comptime_token")) |comptime_token| {
return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
}
@@ -98,64 +106,48 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
return mod.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{});
}
-fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {
- switch (infix_node.op) {
- .Assign => {
- if (infix_node.lhs.tag == .Identifier) {
- const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs);
- const tree = scope.tree();
- const ident_name = tree.tokenSlice(ident.token);
- if (std.mem.eql(u8, ident_name, "_")) {
- return expr(mod, scope, infix_node.rhs);
- } else {
- return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
- }
- } else {
- return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
- }
- },
- .Add => {
- const lhs = try expr(mod, scope, infix_node.lhs);
- const rhs = try expr(mod, scope, infix_node.rhs);
+fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
+ if (infix_node.lhs.tag == .Identifier) {
+ const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs);
+ const tree = scope.tree();
+ const ident_name = tree.tokenSlice(ident.token);
+ if (std.mem.eql(u8, ident_name, "_")) {
+ return expr(mod, scope, infix_node.rhs);
+ } else {
+ return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
+ }
+ } else {
+ return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
+ }
+}
- const tree = scope.tree();
- const src = tree.token_locs[infix_node.op_token].start;
+fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
+ const lhs = try expr(mod, scope, infix_node.lhs);
+ const rhs = try expr(mod, scope, infix_node.rhs);
- return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{});
- },
- .BangEqual,
- .EqualEqual,
- .GreaterThan,
- .GreaterOrEqual,
- .LessThan,
- .LessOrEqual,
- => {
- const lhs = try expr(mod, scope, infix_node.lhs);
- const rhs = try expr(mod, scope, infix_node.rhs);
-
- const tree = scope.tree();
- const src = tree.token_locs[infix_node.op_token].start;
-
- const op: std.math.CompareOperator = switch (infix_node.op) {
- .BangEqual => .neq,
- .EqualEqual => .eq,
- .GreaterThan => .gt,
- .GreaterOrEqual => .gte,
- .LessThan => .lt,
- .LessOrEqual => .lte,
- else => unreachable,
- };
+ const tree = scope.tree();
+ const src = tree.token_locs[infix_node.op_token].start;
- return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{
- .lhs = lhs,
- .op = op,
- .rhs = rhs,
- }, .{});
- },
- else => |op| {
- return mod.failNode(scope, &infix_node.base, "TODO implement infix operator {}", .{op});
- },
- }
+ return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{});
+}
+
+fn cmp(
+ mod: *Module,
+ scope: *Scope,
+ infix_node: *ast.Node.SimpleInfixOp,
+ op: std.math.CompareOperator,
+) InnerError!*zir.Inst {
+ const lhs = try expr(mod, scope, infix_node.lhs);
+ const rhs = try expr(mod, scope, infix_node.rhs);
+
+ const tree = scope.tree();
+ const src = tree.token_locs[infix_node.op_token].start;
+
+ return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{
+ .lhs = lhs,
+ .op = op,
+ .rhs = rhs,
+ }, .{});
}
fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst {
@@ -571,6 +563,47 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
.ErrorSetDecl,
.ContainerDecl,
.Asm,
+ .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,
+ .Range,
+ .Period,
+ .Sub,
+ .SubWrap,
=> false,
.ArrayInitializer,
@@ -579,9 +612,10 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
.StructInitializerDot,
=> true,
- .GroupedExpression => nodeNeedsMemoryLocation(node.cast(ast.Node.GroupedExpression).?.expr),
+ .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr),
- .InfixOp => @panic("TODO nodeNeedsMemoryLocation for InfixOp"),
+ .UnwrapOptional => @panic("TODO nodeNeedsMemoryLocation for UnwrapOptional"),
+ .Catch => @panic("TODO nodeNeedsMemoryLocation for Catch"),
.Await => @panic("TODO nodeNeedsMemoryLocation for Await"),
.Try => @panic("TODO nodeNeedsMemoryLocation for Try"),
.If => @panic("TODO nodeNeedsMemoryLocation for If"),
src-self-hosted/Module.zig
@@ -1954,7 +1954,7 @@ pub fn addZIRInstSpecial(
positionals: std.meta.fieldInfo(T, "positionals").field_type,
kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
) !*T {
- const gen_zir = scope.cast(Scope.GenZIR).?;
+ const gen_zir = scope.getGenZIR();
try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1);
const inst = try newZIRInst(gen_zir.arena, src, T, positionals, kw_args);
gen_zir.instructions.appendAssumeCapacity(&inst.base);
src-self-hosted/translate_c.zig
@@ -1103,11 +1103,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
const enum_ident = try transCreateNodeIdentifier(c, name);
const period_tok = try appendToken(c, .Period, ".");
const field_ident = try transCreateNodeIdentifier(c, field_name);
- const field_access_node = try c.arena.create(ast.Node.InfixOp);
+ const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp);
field_access_node.* = .{
+ .base = .{ .tag = .Period },
.op_token = period_tok,
.lhs = enum_ident,
- .op = .Period,
.rhs = field_ident,
};
cast_node.params()[0] = &field_access_node.base;
@@ -1294,7 +1294,7 @@ fn transBinaryOperator(
const op = ZigClangBinaryOperator_getOpcode(stmt);
const qt = ZigClangBinaryOperator_getType(stmt);
var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.InfixOp.Op = undefined;
+ var op_id: ast.Node.Tag = undefined;
switch (op) {
.Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),
.Comma => {
@@ -1737,25 +1737,22 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool {
fn isBoolRes(res: *ast.Node) bool {
switch (res.tag) {
- .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
- .BoolOr,
- .BoolAnd,
- .EqualEqual,
- .BangEqual,
- .LessThan,
- .GreaterThan,
- .LessOrEqual,
- .GreaterOrEqual,
- => return true,
+ .BoolOr,
+ .BoolAnd,
+ .EqualEqual,
+ .BangEqual,
+ .LessThan,
+ .GreaterThan,
+ .LessOrEqual,
+ .GreaterOrEqual,
+ .BoolNot,
+ .BoolLiteral,
+ => return true,
- else => {},
- },
- .BoolNot => return true,
- .BoolLiteral => return true,
.GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
- else => {},
+
+ else => return false,
}
- return false;
}
fn finishBoolExpr(
@@ -2312,11 +2309,11 @@ fn transInitListExprArray(
&filler_init_node.base
else blk: {
const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**");
- const mul_node = try rp.c.arena.create(ast.Node.InfixOp);
+ const mul_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
mul_node.* = .{
+ .base = .{ .tag = .ArrayMult },
.op_token = mul_tok,
.lhs = &filler_init_node.base,
- .op = .ArrayMult,
.rhs = try transCreateNodeInt(rp.c, leftover_count),
};
break :blk &mul_node.base;
@@ -2326,11 +2323,11 @@ fn transInitListExprArray(
return rhs_node;
}
- const cat_node = try rp.c.arena.create(ast.Node.InfixOp);
+ const cat_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
cat_node.* = .{
+ .base = .{ .tag = .ArrayCat },
.op_token = cat_tok,
.lhs = &init_node.base,
- .op = .ArrayCat,
.rhs = rhs_node,
};
return &cat_node.base;
@@ -2723,11 +2720,11 @@ fn transCase(
const ellips = try appendToken(rp.c, .Ellipsis3, "...");
const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
- const node = try rp.c.arena.create(ast.Node.InfixOp);
+ const node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
node.* = .{
+ .base = .{ .tag = .Range },
.op_token = ellips,
.lhs = lhs_node,
- .op = .Range,
.rhs = rhs_node,
};
break :blk &node.base;
@@ -3153,7 +3150,7 @@ fn transCreatePreCrement(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangUnaryOperator,
- op: ast.Node.InfixOp.Op,
+ op: ast.Node.Tag,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
used: ResultUsed,
@@ -3227,7 +3224,7 @@ fn transCreatePostCrement(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangUnaryOperator,
- op: ast.Node.InfixOp.Op,
+ op: ast.Node.Tag,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
used: ResultUsed,
@@ -3349,10 +3346,10 @@ fn transCreateCompoundAssign(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangCompoundAssignOperator,
- assign_op: ast.Node.InfixOp.Op,
+ assign_op: ast.Node.Tag,
assign_tok_id: std.zig.Token.Id,
assign_bytes: []const u8,
- bin_op: ast.Node.InfixOp.Op,
+ bin_op: ast.Node.Tag,
bin_tok_id: std.zig.Token.Id,
bin_bytes: []const u8,
used: ResultUsed,
@@ -3377,7 +3374,7 @@ fn transCreateCompoundAssign(
// zig: lhs += rhs
if ((is_mod or is_div) and is_signed) {
const op_token = try appendToken(rp.c, .Equal, "=");
- const op_node = try rp.c.arena.create(ast.Node.InfixOp);
+ const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
const builtin = if (is_mod) "@rem" else "@divTrunc";
const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
@@ -3386,9 +3383,9 @@ fn transCreateCompoundAssign(
builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value);
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
op_node.* = .{
+ .base = .{ .tag = .Assign },
.op_token = op_token,
.lhs = lhs_node,
- .op = .Assign,
.rhs = &builtin_node.base,
};
_ = try appendToken(rp.c, .Semicolon, ";");
@@ -3452,7 +3449,7 @@ fn transCreateCompoundAssign(
if ((is_mod or is_div) and is_signed) {
const op_token = try appendToken(rp.c, .Equal, "=");
- const op_node = try rp.c.arena.create(ast.Node.InfixOp);
+ const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
const builtin = if (is_mod) "@rem" else "@divTrunc";
const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node);
@@ -3461,9 +3458,9 @@ fn transCreateCompoundAssign(
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
_ = try appendToken(rp.c, .Semicolon, ";");
op_node.* = .{
+ .base = .{ .tag = .Assign },
.op_token = op_token,
.lhs = ref_node,
- .op = .Assign,
.rhs = &builtin_node.base,
};
_ = try appendToken(rp.c, .Semicolon, ";");
@@ -3716,11 +3713,11 @@ fn maybeSuppressResult(
}
const lhs = try transCreateNodeIdentifier(rp.c, "_");
const op_token = try appendToken(rp.c, .Equal, "=");
- const op_node = try rp.c.arena.create(ast.Node.InfixOp);
+ const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
op_node.* = .{
+ .base = .{ .tag = .Assign },
.op_token = op_token,
.lhs = lhs,
- .op = .Assign,
.rhs = result,
};
return &op_node.base;
@@ -4095,11 +4092,11 @@ fn transCreateNodeAssign(
}
fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {
- const field_access_node = try c.arena.create(ast.Node.InfixOp);
+ const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp);
field_access_node.* = .{
+ .base = .{ .tag = .Period },
.op_token = try appendToken(c, .Period, "."),
.lhs = container,
- .op = .Period,
.rhs = try transCreateNodeIdentifier(c, field_name),
};
return &field_access_node.base;
@@ -4124,7 +4121,7 @@ fn transCreateNodeInfixOp(
rp: RestorePoint,
scope: *Scope,
lhs_node: *ast.Node,
- op: ast.Node.InfixOp.Op,
+ op: ast.Node.Tag,
op_token: ast.TokenIndex,
rhs_node: *ast.Node,
used: ResultUsed,
@@ -4134,11 +4131,11 @@ fn transCreateNodeInfixOp(
try appendToken(rp.c, .LParen, "(")
else
null;
- const node = try rp.c.arena.create(ast.Node.InfixOp);
+ const node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
node.* = .{
+ .base = .{ .tag = op },
.op_token = op_token,
.lhs = lhs_node,
- .op = op,
.rhs = rhs_node,
};
if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base);
@@ -4156,7 +4153,7 @@ fn transCreateNodeBoolInfixOp(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangBinaryOperator,
- op: ast.Node.InfixOp.Op,
+ op: ast.Node.Tag,
used: ResultUsed,
grouped: bool,
) !*ast.Node {
@@ -4536,7 +4533,7 @@ fn transCreateNodeShiftOp(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangBinaryOperator,
- op: ast.Node.InfixOp.Op,
+ op: ast.Node.Tag,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
) !*ast.Node {
@@ -4558,11 +4555,11 @@ fn transCreateNodeShiftOp(
cast_node.params()[1] = rhs;
cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
- const node = try rp.c.arena.create(ast.Node.InfixOp);
+ const node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
node.* = .{
+ .base = .{ .tag = op },
.op_token = op_token,
.lhs = lhs,
- .op = op,
.rhs = &cast_node.base,
};
@@ -5404,11 +5401,11 @@ fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_
// suppress result
const lhs = try transCreateNodeIdentifier(c, "_");
const op_token = try appendToken(c, .Equal, "=");
- const op_node = try c.arena.create(ast.Node.InfixOp);
+ const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
op_node.* = .{
+ .base = .{ .tag = .Assign },
.op_token = op_token,
.lhs = lhs,
- .op = .Assign,
.rhs = last,
};
try block_scope.statements.append(&op_node.base);
@@ -5787,9 +5784,60 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}
}
+fn nodeIsInfixOp(tag: ast.Node.Tag) bool {
+ return switch (tag) {
+ .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,
+ .UnwrapOptional,
+ .Catch,
+ => true,
+
+ else => false,
+ };
+}
+
fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
if (!isBoolRes(node)) {
- if (node.tag != .InfixOp) return node;
+ if (!nodeIsInfixOp(node.tag)) return node;
const group_node = try c.arena.create(ast.Node.GroupedExpression);
group_node.* = .{
@@ -5808,7 +5856,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
if (isBoolRes(node)) {
- if (node.tag != .InfixOp) return node;
+ if (!nodeIsInfixOp(node.tag)) return node;
const group_node = try c.arena.create(ast.Node.GroupedExpression);
group_node.* = .{
@@ -5821,11 +5869,11 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
const op_token = try appendToken(c, .BangEqual, "!=");
const zero = try transCreateNodeInt(c, 0);
- const res = try c.arena.create(ast.Node.InfixOp);
+ const res = try c.arena.create(ast.Node.SimpleInfixOp);
res.* = .{
+ .base = .{ .tag = .BangEqual },
.op_token = op_token,
.lhs = node,
- .op = .BangEqual,
.rhs = zero,
};
const group_node = try c.arena.create(ast.Node.GroupedExpression);
@@ -5842,7 +5890,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
while (true) {
const tok = it.next().?;
var op_token: ast.TokenIndex = undefined;
- var op_id: ast.Node.InfixOp.Op = undefined;
+ var op_id: ast.Node.Tag = undefined;
var bool_op = false;
switch (tok.id) {
.Period => {
@@ -6049,11 +6097,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
const lhs_node = try cast_fn(c, node);
const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
- const op_node = try c.arena.create(ast.Node.InfixOp);
+ const op_node = try c.arena.create(ast.Node.SimpleInfixOp);
op_node.* = .{
+ .base = .{ .tag = op_id },
.op_token = op_token,
.lhs = lhs_node,
- .op = op_id,
.rhs = try cast_fn(c, rhs_node),
};
node = &op_node.base;
@@ -6131,10 +6179,9 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
}
},
- .InfixOp => {
- const infix = node.cast(ast.Node.InfixOp).?;
- if (infix.op != .Period)
- return null;
+ .Period => {
+ const infix = node.castTag(.Period).?;
+
if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
for (container.fieldsAndDecls()) |field_ref| {
@@ -6161,9 +6208,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
return getContainer(c, ty);
}
}
- } else if (ref.cast(ast.Node.InfixOp)) |infix| {
- if (infix.op != .Period)
- return null;
+ } else if (ref.castTag(.Period)) |infix| {
if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
for (container.fieldsAndDecls()) |field_ref| {