Commit 1ac28eed83

Andrew Kelley <andrew@ziglang.org>
2020-07-21 00:52:24
stage2 AST: rename OptionalUnwrap to OrElse
preparing to flatten suffix operations AST
1 parent 1cfe43d
Changed files (4)
lib
src-self-hosted
lib/std/zig/ast.zig
@@ -453,7 +453,7 @@ pub const Node = struct {
         Range,
         Sub,
         SubWrap,
-        UnwrapOptional,
+        OrElse,
 
         // SimplePrefixOp
         AddressOf,
@@ -582,7 +582,7 @@ pub const Node = struct {
                 .Range,
                 .Sub,
                 .SubWrap,
-                .UnwrapOptional,
+                .OrElse,
                 => SimpleInfixOp,
 
                 .AddressOf,
lib/std/zig/parse.zig
@@ -1486,7 +1486,7 @@ const Parser = struct {
                     .Range,
                     .Sub,
                     .SubWrap,
-                    .UnwrapOptional,
+                    .OrElse,
                     => node.cast(Node.SimpleInfixOp).?.lhs = res,
 
                     else => unreachable,
@@ -1563,7 +1563,7 @@ const Parser = struct {
                         .Range,
                         .Sub,
                         .SubWrap,
-                        .UnwrapOptional,
+                        .OrElse,
                         => node.cast(Node.SimpleInfixOp).?.lhs = res,
                         else => unreachable,
                     }
@@ -2425,7 +2425,7 @@ const Parser = struct {
             .Ampersand => .BitAnd,
             .Caret => .BitXor,
             .Pipe => .BitOr,
-            .Keyword_orelse => .UnwrapOptional,
+            .Keyword_orelse => .OrElse,
             .Keyword_catch => {
                 const payload = try p.parsePayload();
                 const node = try p.arena.allocator.create(Node.Catch);
lib/std/zig/render.zig
@@ -503,7 +503,7 @@ fn renderExpression(
         .Range,
         .Sub,
         .SubWrap,
-        .UnwrapOptional,
+        .OrElse,
         => {
             const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base);
 
@@ -2656,7 +2656,7 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
         .Range,
         .Sub,
         .SubWrap,
-        .UnwrapOptional,
+        .OrElse,
         => true,
 
         else => false,
src-self-hosted/astgen.zig
@@ -88,7 +88,7 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop
     // 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 (nodeNeedsMemoryLocation(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);
@@ -579,120 +579,130 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
     return null;
 }
 
-fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
-    return switch (node.tag) {
-        .Root,
-        .Use,
-        .TestDecl,
-        .DocComment,
-        .SwitchCase,
-        .SwitchElse,
-        .Else,
-        .Payload,
-        .PointerPayload,
-        .PointerIndexPayload,
-        .ContainerField,
-        .ErrorTag,
-        .FieldInitializer,
-        => unreachable,
-
-        .ControlFlowExpression,
-        .BitNot,
-        .BoolNot,
-        .VarDecl,
-        .Defer,
-        .AddressOf,
-        .OptionalType,
-        .Negation,
-        .NegationWrap,
-        .Resume,
-        .ArrayType,
-        .ArrayTypeSentinel,
-        .PtrType,
-        .SliceType,
-        .Suspend,
-        .AnyType,
-        .ErrorType,
-        .FnProto,
-        .AnyFrameType,
-        .IntegerLiteral,
-        .FloatLiteral,
-        .EnumLiteral,
-        .StringLiteral,
-        .MultilineStringLiteral,
-        .CharLiteral,
-        .BoolLiteral,
-        .NullLiteral,
-        .UndefinedLiteral,
-        .Unreachable,
-        .Identifier,
-        .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,
-        .ArrayInitializerDot,
-        .StructInitializer,
-        .StructInitializerDot,
-        => true,
-
-        .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr),
-
-        .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"),
-        .SuffixOp => @panic("TODO nodeNeedsMemoryLocation for SuffixOp"),
-        .Call => @panic("TODO nodeNeedsMemoryLocation for Call"),
-        .Switch => @panic("TODO nodeNeedsMemoryLocation for Switch"),
-        .While => @panic("TODO nodeNeedsMemoryLocation for While"),
-        .For => @panic("TODO nodeNeedsMemoryLocation for For"),
-        .BuiltinCall => @panic("TODO nodeNeedsMemoryLocation for BuiltinCall"),
-        .Comptime => @panic("TODO nodeNeedsMemoryLocation for Comptime"),
-        .Nosuspend => @panic("TODO nodeNeedsMemoryLocation for Nosuspend"),
-        .Block => @panic("TODO nodeNeedsMemoryLocation for Block"),
-    };
+fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool {
+    var node = start_node;
+    while (true) {
+        switch (node.tag) {
+            .Root,
+            .Use,
+            .TestDecl,
+            .DocComment,
+            .SwitchCase,
+            .SwitchElse,
+            .Else,
+            .Payload,
+            .PointerPayload,
+            .PointerIndexPayload,
+            .ContainerField,
+            .ErrorTag,
+            .FieldInitializer,
+            => unreachable,
+
+            .ControlFlowExpression,
+            .BitNot,
+            .BoolNot,
+            .VarDecl,
+            .Defer,
+            .AddressOf,
+            .OptionalType,
+            .Negation,
+            .NegationWrap,
+            .Resume,
+            .ArrayType,
+            .ArrayTypeSentinel,
+            .PtrType,
+            .SliceType,
+            .Suspend,
+            .AnyType,
+            .ErrorType,
+            .FnProto,
+            .AnyFrameType,
+            .IntegerLiteral,
+            .FloatLiteral,
+            .EnumLiteral,
+            .StringLiteral,
+            .MultilineStringLiteral,
+            .CharLiteral,
+            .BoolLiteral,
+            .NullLiteral,
+            .UndefinedLiteral,
+            .Unreachable,
+            .Identifier,
+            .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,
+            => return false,
+
+            // Forward the question to a sub-expression.
+            .GroupedExpression => node = node.castTag(.GroupedExpression).?.expr,
+            .Try => node = node.castTag(.Try).?.rhs,
+            .Await => node = node.castTag(.Await).?.rhs,
+            .Catch => node = node.castTag(.Catch).?.rhs,
+            .OrElse => node = node.castTag(.OrElse).?.rhs,
+            .Comptime => node = node.castTag(.Comptime).?.expr,
+            .Nosuspend => node = node.castTag(.Nosuspend).?.expr,
+
+            // True because these are exactly the expressions we need memory locations for.
+            .ArrayInitializer,
+            .ArrayInitializerDot,
+            .StructInitializer,
+            .StructInitializerDot,
+            => return true,
+
+            // True because depending on comptime conditions, sub-expressions
+            // may be the kind that need memory locations.
+            .While,
+            .For,
+            .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.
+            .If => return node.castTag(.If).?.@"else" != null,
+            .Block => return node.castTag(.Block).?.label != null,
+        }
+    }
 }