Commit b424cd75ab

Jimmi Holst Christensen <jhc@liab.dk>
2018-04-03 12:33:06
std.zig.parser refactored call, slice and array access to be suffix op
1 parent 22e38ff
Changed files (2)
std/zig/ast.zig
@@ -17,6 +17,7 @@ pub const Node = struct {
         Block,
         InfixOp,
         PrefixOp,
+        SuffixOp,
         IntegerLiteral,
         FloatLiteral,
         StringLiteral,
@@ -29,9 +30,6 @@ pub const Node = struct {
         Unreachable,
         ErrorType,
         BuiltinCall,
-        Call,
-        ArrayAccess,
-        SliceExpression,
         LineComment,
         TestDecl,
     };
@@ -46,6 +44,7 @@ pub const Node = struct {
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
             Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
             Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
+            Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
             Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
             Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
             Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),
@@ -58,9 +57,6 @@ pub const Node = struct {
             Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
             Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
             Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
-            Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index),
-            Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).iterate(index),
-            Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).iterate(index),
             Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
             Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),
         };
@@ -76,6 +72,7 @@ pub const Node = struct {
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
             Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
             Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
+            Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
             Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(),
             Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),
             Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),
@@ -88,9 +85,6 @@ pub const Node = struct {
             Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
             Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
             Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
-            Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(),
-            Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).firstToken(),
-            Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).firstToken(),
             Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
             Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),
         };
@@ -106,6 +100,7 @@ pub const Node = struct {
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
             Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
             Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
+            Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
             Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(),
             Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),
             Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),
@@ -118,9 +113,6 @@ pub const Node = struct {
             Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
             Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
             Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
-            Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(),
-            Id.ArrayAccess => @fieldParentPtr(NodeArrayAccess, "base", base).lastToken(),
-            Id.SliceExpression => @fieldParentPtr(NodeSliceExpression, "base", base).lastToken(),
             Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
             Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
         };
@@ -493,20 +485,28 @@ pub const NodePrefixOp = struct {
         var i = index;
 
         switch (self.op) {
+            PrefixOp.SliceType => |addr_of_info| {
+                if (addr_of_info.align_expr) |align_expr| {
+                    if (i < 1) return align_expr;
+                    i -= 1;
+                }
+            },
             PrefixOp.AddrOf => |addr_of_info| {
                 if (addr_of_info.align_expr) |align_expr| {
                     if (i < 1) return align_expr;
                     i -= 1;
                 }
             },
+            PrefixOp.ArrayType => |size_expr| {
+                if (i < 1) return size_expr;
+                i -= 1;
+            },
             PrefixOp.BitNot,
             PrefixOp.BoolNot,
             PrefixOp.Deref,
             PrefixOp.Negation,
             PrefixOp.NegationWrap,
             PrefixOp.Return,
-            PrefixOp.ArrayType,
-            PrefixOp.SliceType,
             PrefixOp.Try,
             PrefixOp.UnwrapMaybe => {},
         }
@@ -526,6 +526,76 @@ pub const NodePrefixOp = struct {
     }
 };
 
+pub const NodeSuffixOp = struct {
+    base: Node,
+    lhs: &Node,
+    op: SuffixOp,
+    rtoken: Token,
+
+    const SuffixOp = union(enum) {
+        Call: CallInfo,
+        ArrayAccess: &Node,
+        Slice: SliceRange,
+        ArrayInitializer: ArrayList(&Node),
+        StructInitializer: ArrayList(&Node),
+    };
+
+    const CallInfo = struct {
+        params: ArrayList(&Node),
+        is_async: bool,
+    };
+
+    const SliceRange = struct {
+        start: &Node,
+        end: ?&Node,
+    };
+
+    pub fn iterate(self: &NodeSuffixOp, index: usize) ?&Node {
+        var i = index;
+
+        if (i < 1) return self.lhs;
+        i -= 1;
+
+        switch (self.op) {
+            SuffixOp.Call => |call_info| {
+                if (i < call_info.params.len) return call_info.params.at(i);
+                i -= call_info.params.len;
+            },
+            SuffixOp.ArrayAccess => |index_expr| {
+                if (i < 1) return index_expr;
+                i -= 1;
+            },
+            SuffixOp.Slice => |range| {
+                if (i < 1) return range.start;
+                i -= 1;
+
+                if (range.end) |end| {
+                    if (i < 1) return end;
+                    i -= 1;
+                }
+            },
+            SuffixOp.ArrayInitializer => |exprs| {
+                if (i < exprs.len) return exprs.at(i);
+                i -= exprs.len;
+            },
+            SuffixOp.StructInitializer => |fields| {
+                if (i < fields.len) return fields.at(i);
+                i -= fields.len;
+            },
+        }
+
+        return null;
+    }
+
+    pub fn firstToken(self: &NodeSuffixOp) Token {
+        return self.lhs.firstToken();
+    }
+
+    pub fn lastToken(self: &NodeSuffixOp) Token {
+        return self.rtoken;
+    }
+};
+
 pub const NodeIntegerLiteral = struct {
     base: Node,
     token: Token,
@@ -584,91 +654,6 @@ pub const NodeBuiltinCall = struct {
     }
 };
 
-pub const NodeCall = struct {
-    base: Node,
-    callee: &Node,
-    params: ArrayList(&Node),
-    rparen_token: Token,
-
-    pub fn iterate(self: &NodeCall, index: usize) ?&Node {
-        var i = index;
-
-        if (i < 1) return self.callee;
-        i -= 1;
-
-        if (i < self.params.len) return self.params.at(i);
-        i -= self.params.len;
-
-        return null;
-    }
-
-    pub fn firstToken(self: &NodeCall) Token {
-        return self.callee.firstToken();
-    }
-
-    pub fn lastToken(self: &NodeCall) Token {
-        return self.rparen_token;
-    }
-};
-
-pub const NodeArrayAccess = struct {
-    base: Node,
-    expr: &Node,
-    index: &Node,
-    rbracket_token: Token,
-
-    pub fn iterate(self: &NodeArrayAccess, index: usize) ?&Node {
-        var i = index;
-
-        if (i < 1) return self.expr;
-        i -= 1;
-
-        if (i < 1) return self.index;
-        i -= 1;
-
-        return null;
-    }
-
-    pub fn firstToken(self: &NodeArrayAccess) Token {
-        return self.expr.firstToken();
-    }
-
-    pub fn lastToken(self: &NodeArrayAccess) Token {
-        return self.rbracket_token;
-    }
-};
-
-pub const NodeSliceExpression = struct {
-    base: Node,
-    expr: &Node,
-    start: &Node,
-    end: ?&Node,
-    rbracket_token: Token,
-
-    pub fn iterate(self: &NodeSliceExpression, index: usize) ?&Node {
-        var i = index;
-
-        if (i < 1) return self.callee;
-        i -= 1;
-
-        if (i < 1) return self.start;
-        i -= 1;
-
-        if (i < 1) return self.end;
-        i -= 1;
-
-        return null;
-    }
-
-    pub fn firstToken(self: &NodeSliceExpression) Token {
-        return self.expr.firstToken();
-    }
-
-    pub fn lastToken(self: &NodeSliceExpression) Token {
-        return self.rbracket_token;
-    }
-};
-
 pub const NodeStringLiteral = struct {
     base: Node,
     token: Token,
std/zig/parser.zig
@@ -87,7 +87,7 @@ pub const Parser = struct {
         AfterOperand,
         InfixOp: &ast.NodeInfixOp,
         PrefixOp: &ast.NodePrefixOp,
-        SuffixOp: &ast.Node,
+        SuffixOp: &ast.NodeSuffixOp,
         SliceOrArrayAccess,
         AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
         TypeExpr: DestPtr,
@@ -602,20 +602,19 @@ pub const Parser = struct {
                     } else if (token.id == Token.Id.LParen) {
                         self.putBackToken(token);
 
-                        const node = try arena.create(ast.NodeCall);
-                        *node = ast.NodeCall {
-                            .base = self.initNode(ast.Node.Id.Call),
-                            .callee = undefined,
-                            .params = ArrayList(&ast.Node).init(arena),
-                            .rparen_token = undefined,
-                        };
-                        try stack.append(State { .SuffixOp = &node.base });
+                        const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
+                            .Call = ast.NodeSuffixOp.CallInfo {
+                                .params = ArrayList(&ast.Node).init(arena),
+                                .is_async = false, // TODO: ASYNC
+                            }
+                        });
+                        try stack.append(State { .SuffixOp = node });
                         try stack.append(State.AfterOperand);
-                        try stack.append(State {.ExprListItemOrEnd = &node.params });
+                        try stack.append(State {.ExprListItemOrEnd = &node.op.Call.params });
                         try stack.append(State {
                             .ExpectTokenSave = ExpectTokenSave {
                                 .id = Token.Id.LParen,
-                                .ptr = &node.rparen_token,
+                                .ptr = &node.rtoken,
                             },
                         });
                         continue;
@@ -643,16 +642,14 @@ pub const Parser = struct {
 
                                     switch (rbracket_or_ellipsis2_token.id) {
                                         Token.Id.Ellipsis2 => {
-                                            const node = try arena.create(ast.NodeSliceExpression);
-                                            *node = ast.NodeSliceExpression {
-                                                .base = self.initNode(ast.Node.Id.SliceExpression),
-                                                .expr = undefined,
-                                                .start = expression,
-                                                .end = null,
-                                                .rbracket_token = undefined,
-                                            };
-
-                                            try stack.append(State { .SuffixOp = &node.base });
+                                            const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
+                                                .Slice = ast.NodeSuffixOp.SliceRange {
+                                                    .start = expression,
+                                                    .end = null,
+                                                }
+                                            });
+
+                                            try stack.append(State { .SuffixOp = node });
                                             try stack.append(State.AfterOperand);
 
                                             const rbracket_token = self.getNextToken();
@@ -661,24 +658,21 @@ pub const Parser = struct {
                                                 try stack.append(State {
                                                     .ExpectTokenSave = ExpectTokenSave {
                                                         .id = Token.Id.RBracket,
-                                                        .ptr = &node.rbracket_token,
+                                                        .ptr = &node.rtoken,
                                                     }
                                                 });
-                                                try stack.append(State { .Expression = DestPtr { .NullableField = &node.end } });
+                                                try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } });
                                             } else {
-                                                node.rbracket_token = rbracket_token;
+                                                node.rtoken = rbracket_token;
                                             }
                                             break;
                                         },
                                         Token.Id.RBracket => {
-                                            const node = try arena.create(ast.NodeArrayAccess);
-                                            *node = ast.NodeArrayAccess {
-                                                .base = self.initNode(ast.Node.Id.ArrayAccess),
-                                                .expr = undefined,
-                                                .index = expression,
-                                                .rbracket_token = token,
-                                            };
-                                            try stack.append(State { .SuffixOp = &node.base });
+                                            const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
+                                                .ArrayAccess = expression
+                                            });
+                                            node.rtoken = token;
+                                            try stack.append(State { .SuffixOp = node });
                                             try stack.append(State.AfterOperand);
                                             break;
                                         },
@@ -950,27 +944,8 @@ pub const Parser = struct {
         while (true) {
             switch (stack.pop()) {
                 State.SuffixOp => |suffix_op| {
-                    switch (suffix_op.id) {
-                        ast.Node.Id.Call => {
-                            const call = @fieldParentPtr(ast.NodeCall, "base", suffix_op);
-                            *left_leaf_ptr = &call.base;
-                            left_leaf_ptr = &call.callee;
-                            continue;
-                        },
-                        ast.Node.Id.ArrayAccess => {
-                            const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", suffix_op);
-                            *left_leaf_ptr = &arr_access.base;
-                            left_leaf_ptr = &arr_access.expr;
-                            continue;
-                        },
-                        ast.Node.Id.SliceExpression => {
-                            const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", suffix_op);
-                            *left_leaf_ptr = &slice_expr.base;
-                            left_leaf_ptr = &slice_expr.expr;
-                            continue;
-                        },
-                        else => unreachable,
-                    }
+                    *left_leaf_ptr = &suffix_op.base;
+                    left_leaf_ptr = &suffix_op.lhs;
                 },
                 State.Operand => |operand| {
                     *left_leaf_ptr = operand;
@@ -1172,6 +1147,18 @@ pub const Parser = struct {
         return node;
     }
 
+    fn createSuffixOp(self: &Parser, arena: &mem.Allocator, op: &const ast.NodeSuffixOp.SuffixOp) !&ast.NodeSuffixOp {
+        const node = try arena.create(ast.NodeSuffixOp);
+
+        *node = ast.NodeSuffixOp {
+            .base = self.initNode(ast.Node.Id.SuffixOp),
+            .lhs = undefined,
+            .op = *op,
+            .rtoken = undefined,
+        };
+        return node;
+    }
+
     fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier {
         const node = try arena.create(ast.NodeIdentifier);
 
@@ -1625,6 +1612,43 @@ pub const Parser = struct {
                             ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"),
                         }
                     },
+                    ast.Node.Id.SuffixOp => {
+                        const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", base);
+
+                        switch (suffix_op.op) {
+                            ast.NodeSuffixOp.SuffixOp.Call => |call_info| {
+                                try stack.append(RenderState { .Text = ")"});
+                                var i = call_info.params.len;
+                                while (i != 0) {
+                                    i -= 1;
+                                    const param_node = call_info.params.at(i);
+                                    try stack.append(RenderState { .Expression = param_node});
+                                    if (i != 0) {
+                                        try stack.append(RenderState { .Text = ", " });
+                                    }
+                                }
+                                try stack.append(RenderState { .Text = "("});
+                            },
+                            ast.NodeSuffixOp.SuffixOp.ArrayAccess => |index_expr| {
+                                try stack.append(RenderState { .Text = "]"});
+                                try stack.append(RenderState { .Expression = index_expr});
+                                try stack.append(RenderState { .Text = "["});
+                            },
+                            ast.NodeSuffixOp.SuffixOp.Slice => |range| {
+                                try stack.append(RenderState { .Text = "]"});
+                                if (range.end) |end| {
+                                    try stack.append(RenderState { .Expression = end});
+                                }
+                                try stack.append(RenderState { .Text = ".."});
+                                try stack.append(RenderState { .Expression = range.start});
+                                try stack.append(RenderState { .Text = "["});
+                            },
+                            ast.NodeSuffixOp.SuffixOp.StructInitializer => @panic("TODO: StructInitializer"),
+                            ast.NodeSuffixOp.SuffixOp.ArrayInitializer => @panic("TODO: ArrayInitializer"),
+                        }
+
+                        try stack.append(RenderState { .Expression = suffix_op.lhs });
+                    },
                     ast.Node.Id.IntegerLiteral => {
                         const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);
                         try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token));
@@ -1693,39 +1717,6 @@ pub const Parser = struct {
                             }
                         }
                     },
-                    ast.Node.Id.Call => {
-                        const call = @fieldParentPtr(ast.NodeCall, "base", base);
-                        try stack.append(RenderState { .Text = ")"});
-                        var i = call.params.len;
-                        while (i != 0) {
-                            i -= 1;
-                            const param_node = call.params.at(i);
-                            try stack.append(RenderState { .Expression = param_node});
-                            if (i != 0) {
-                                try stack.append(RenderState { .Text = ", " });
-                            }
-                        }
-                        try stack.append(RenderState { .Text = "("});
-                        try stack.append(RenderState { .Expression = call.callee });
-                    },
-                    ast.Node.Id.ArrayAccess => {
-                        const arr_access = @fieldParentPtr(ast.NodeArrayAccess, "base", base);
-                        try stack.append(RenderState { .Text = "]"});
-                        try stack.append(RenderState { .Expression = arr_access.index});
-                        try stack.append(RenderState { .Text = "["});
-                        try stack.append(RenderState { .Expression = arr_access.expr });
-                    },
-                    ast.Node.Id.SliceExpression => {
-                        const slice_expr = @fieldParentPtr(ast.NodeSliceExpression, "base", base);
-                        try stack.append(RenderState { .Text = "]"});
-                        if (slice_expr.end) |end| {
-                            try stack.append(RenderState { .Expression = end});
-                        }
-                        try stack.append(RenderState { .Text = ".."});
-                        try stack.append(RenderState { .Expression = slice_expr.start});
-                        try stack.append(RenderState { .Text = "["});
-                        try stack.append(RenderState { .Expression = slice_expr.expr});
-                    },
                     ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
                     ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),