diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index b91cac7865..7fee55c71e 100644 --- a/lib/std/zig/ast.zig +++ b/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, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index b02cdcc1fd..c6d48c946d 100644 --- a/lib/std/zig/parse.zig +++ b/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); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 7f8a18299b..c805178523 100644 --- a/lib/std/zig/render.zig +++ b/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, diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 9cdba61e01..917fa009bb 100644 --- a/src-self-hosted/astgen.zig +++ b/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, +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, - => false, + .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, - .ArrayInitializer, - .ArrayInitializerDot, - .StructInitializer, - .StructInitializerDot, - => true, + // 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, - .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr), + // True because these are exactly the expressions we need memory locations for. + .ArrayInitializer, + .ArrayInitializerDot, + .StructInitializer, + .StructInitializerDot, + => return true, - .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"), - }; + // 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, + } + } }