diff --git a/pkl-core/src/main/java/org/pkl/core/ast/builder/SymbolTable.java b/pkl-core/src/main/java/org/pkl/core/ast/builder/SymbolTable.java index 20c856fd4..4f2eb64fc 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/builder/SymbolTable.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/builder/SymbolTable.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -327,6 +327,8 @@ public final boolean isClassScope() { } public final boolean isClassMemberScope() { + var effectiveScope = skipLambdaScopes(); + var parent = effectiveScope.parent; if (parent == null) return false; return parent.isClassScope() diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeSuperMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeSuperMethodNode.java index 720835ccf..fffc4ed58 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeSuperMethodNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeSuperMethodNode.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.pkl.core.ast.ExpressionNode; import org.pkl.core.ast.member.ClassMethod; import org.pkl.core.runtime.Identifier; +import org.pkl.core.runtime.VmFunction; import org.pkl.core.runtime.VmUtils; public abstract class InvokeSuperMethodNode extends ExpressionNode { @@ -66,6 +67,10 @@ protected Object eval( protected ClassMethod findSupermethod(VirtualFrame frame) { var owner = VmUtils.getOwner(frame); + while (owner instanceof VmFunction) { + owner = owner.getEnclosingOwner(); + } + assert owner != null : "VmFunction always has a parent"; assert owner.isPrototype(); var superclass = owner.getVmClass().getSuperclass(); diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/classes/supercallsInLet.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/classes/supercallsInLet.pkl new file mode 100644 index 000000000..397ef406c --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/classes/supercallsInLet.pkl @@ -0,0 +1,44 @@ +open class A { + function foo() = "a" +} + +class B extends A { + function foo() = + let (bar = "b") + super.foo() + bar +} + +local b = new B {} + +res1 = b.foo() + +// Also test with property access +open class C { + value = "c" +} + +class D extends C { + result = + let (x = "d") + super.value + x +} + +local d = new D {} + +res2 = d.result + +// Test with nested let expressions +open class E { + function getValue() = "e" +} + +class F extends E { + function getValue() = + let (x = "f") + let (y = " and " + x) + super.getValue() + y +} + +local f = new F {} + +res3 = f.getValue() diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/classes/supercallsInLet.pcf b/pkl-core/src/test/files/LanguageSnippetTests/output/classes/supercallsInLet.pcf new file mode 100644 index 000000000..f9a9460f3 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/classes/supercallsInLet.pcf @@ -0,0 +1,3 @@ +res1 = "ab" +res2 = "cd" +res3 = "e and f"