Commit d04346d2ac

Jimmi Holst Christensen <jhc@liab.dk>
2018-04-09 13:07:46
ast.zig.parser now parses defer statements
1 parent c19f5a2
Changed files (3)
std/zig/ast.zig
@@ -20,6 +20,7 @@ pub const Node = struct {
         FnProto,
         ParamDecl,
         Block,
+        Defer,
         ErrorPayload,
         ValuePayload,
         ValueIndexPayload,
@@ -65,6 +66,7 @@ pub const Node = struct {
             Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
             Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
+            Id.Defer => @fieldParentPtr(NodeDefer, "base", base).iterate(index),
             Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).iterate(index),
             Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).iterate(index),
             Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).iterate(index),
@@ -111,6 +113,7 @@ pub const Node = struct {
             Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
             Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
+            Id.Defer => @fieldParentPtr(NodeDefer, "base", base).firstToken(),
             Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).firstToken(),
             Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).firstToken(),
             Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).firstToken(),
@@ -157,6 +160,7 @@ pub const Node = struct {
             Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
             Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
             Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
+            Id.Defer => @fieldParentPtr(NodeDefer, "base", base).lastToken(),
             Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).lastToken(),
             Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).lastToken(),
             Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).lastToken(),
@@ -573,6 +577,35 @@ pub const NodeBlock = struct {
     }
 };
 
+pub const NodeDefer = struct {
+    base: Node,
+    defer_token: Token,
+    kind: Kind,
+    expr: &Node,
+
+    const Kind = enum {
+        Error,
+        Unconditional,
+    };
+
+    pub fn iterate(self: &NodeDefer, index: usize) ?&Node {
+        var i = index;
+
+        if (i < 1) return self.expr;
+        i -= 1;
+
+        return null;
+    }
+
+    pub fn firstToken(self: &NodeDefer) Token {
+        return self.defer_token;
+    }
+
+    pub fn lastToken(self: &NodeDefer) Token {
+        return self.expr.lastToken();
+    }
+};
+
 pub const NodeErrorPayload = struct {
     base: Node,
     lpipe: Token,
std/zig/parser.zig
@@ -2140,6 +2140,24 @@ pub const Parser = struct {
                             stack.append(State { .VarDecl = var_decl }) catch unreachable;
                             continue;
                         },
+                        Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
+                            const node = try arena.create(ast.NodeDefer);
+                            *node = ast.NodeDefer {
+                                .base = self.initNode(ast.Node.Id.Defer),
+                                .defer_token = next,
+                                .kind = switch (next.id) {
+                                    Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional,
+                                    Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error,
+                                    else => unreachable,
+                                },
+                                .expr = undefined,
+                            };
+                            try block.statements.append(&node.base);
+
+                            stack.append(State { .Semicolon = &node.base }) catch unreachable;
+                            try stack.append(State { .Expression = DestPtr{.Field = &node.expr } });
+                            continue;
+                        },
                         Token.Id.LBrace => {
                             const inner_block = try self.createBlock(arena, (?Token)(null), next);
                             try block.statements.append(&inner_block.base);
@@ -2218,6 +2236,10 @@ pub const Parser = struct {
                     const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
                     n = else_node.body;
                 },
+                ast.Node.Id.Defer => {
+                    const defer_node = @fieldParentPtr(ast.NodeDefer, "base", n);
+                    n = defer_node.expr;
+                },
                 else => return true,
             }
         }
@@ -2912,6 +2934,11 @@ pub const Parser = struct {
                             }
                         }
                     },
+                    ast.Node.Id.Defer => {
+                        const defer_node = @fieldParentPtr(ast.NodeDefer, "base", base);
+                        try stream.print("{} ", self.tokenizer.getTokenSlice(defer_node.defer_token));
+                        try stack.append(RenderState { .Expression = defer_node.expr });
+                    },
                     ast.Node.Id.InfixOp => {
                         const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base);
                         try stack.append(RenderState { .Expression = prefix_op_node.rhs });
std/zig/tokenizer.zig
@@ -26,6 +26,7 @@ pub const Token = struct {
         KeywordId{.bytes="defer", .id = Id.Keyword_defer},
         KeywordId{.bytes="else", .id = Id.Keyword_else},
         KeywordId{.bytes="enum", .id = Id.Keyword_enum},
+        KeywordId{.bytes="errdefer", .id = Id.Keyword_errdefer},
         KeywordId{.bytes="error", .id = Id.Keyword_error},
         KeywordId{.bytes="export", .id = Id.Keyword_export},
         KeywordId{.bytes="extern", .id = Id.Keyword_extern},
@@ -151,6 +152,7 @@ pub const Token = struct {
         Keyword_defer,
         Keyword_else,
         Keyword_enum,
+        Keyword_errdefer,
         Keyword_error,
         Keyword_export,
         Keyword_extern,