diff --git a/pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java b/pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java index 22836aaa9..d769acbef 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java @@ -109,6 +109,7 @@ import org.pkl.core.ast.expression.literal.PropertiesLiteralNodeGen; import org.pkl.core.ast.expression.literal.SetLiteralNode; import org.pkl.core.ast.expression.literal.TrueLiteralNode; +import org.pkl.core.ast.expression.member.InferParentWithinMethodArgumentNode; import org.pkl.core.ast.expression.member.InferParentWithinMethodNode; import org.pkl.core.ast.expression.member.InferParentWithinObjectMethodNode; import org.pkl.core.ast.expression.member.InferParentWithinPropertyNodeGen; @@ -998,6 +999,17 @@ private ExpressionNode doVisitNewExprWithInferredParent(NewExpr expr) { .evalError("cannotInferParent") .withSourceSection(createSourceSection(expr.newSpan())) .build(); + } else if (parent instanceof ArgumentList argumentList) { + // cases we can't cover currently + // - FunctionN.apply: the parameter type nodes are not stored + // - pkl.base intrinsic constructorts: List(), Set(), Map(), Bytes() + // - generic methods: pkl.base#Pair(), etc. + // these will throw cannotInferParent at runtime + + var sourceSection = createSourceSection(expr.newSpan()); + var argIndex = argumentList.getArguments().indexOf(child); + inferredParentNode = + new InferParentWithinMethodArgumentNode(sourceSection, language, argIndex); } else { throw exceptionBuilder() .evalError("cannotInferParent") diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalMethodNode.java index bb019be8e..195bd77c6 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalMethodNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalMethodNode.java @@ -21,7 +21,8 @@ import org.pkl.core.runtime.Identifier; import org.pkl.core.runtime.VmUtils; -public abstract sealed class AbstractInvokeLexicalMethodNode extends AbstractInvokeMethodNode +public abstract sealed class AbstractInvokeLexicalMethodNode + extends AbstractInvokeLexicalOrQualifiedMethodNode permits InvokeLexicalClassMethodNode, InvokeLexicalObjectMethodNode { private final int levelsUp; diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalOrQualifiedMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalOrQualifiedMethodNode.java new file mode 100644 index 000000000..952dd8e4d --- /dev/null +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeLexicalOrQualifiedMethodNode.java @@ -0,0 +1,96 @@ +/* + * Copyright © 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pkl.core.ast.expression.member; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.source.SourceSection; +import org.jspecify.annotations.Nullable; +import org.pkl.core.ast.ExpressionNode; +import org.pkl.core.ast.member.Method; +import org.pkl.core.runtime.Identifier; +import org.pkl.core.runtime.VmObjectLike; + +/** + * A non-virtual (statically dispatched) method call. + * + *
Subclasses differ only in how they obtain the {@code owner}/{@code receiver} that the method + * is invoked on: either by walking the frame chain ({@link InvokeLexicalClassMethodNode}, {@link + * InvokeLexicalObjectMethodNode}), or off of an explicit receiver expression ({@link + * InvokeQualifiedClassMethodNode}, {@link InvokeQualifiedObjectMethodNode}). + */ +public abstract sealed class AbstractInvokeLexicalOrQualifiedMethodNode + extends AbstractInvokeMethodNode + permits AbstractInvokeQualifiedMethodNode, AbstractInvokeLexicalMethodNode { + + protected final Identifier methodName; + private final boolean needsConst; + @Children private ExpressionNode[] argumentNodes; + @Child private @Nullable DirectCallNode callNode; + @CompilationFinal protected boolean isConstChecked; + + protected AbstractInvokeLexicalOrQualifiedMethodNode( + SourceSection sourceSection, + Identifier methodName, + ExpressionNode[] argumentNodes, + boolean needsConst) { + super(sourceSection); + this.methodName = methodName; + this.argumentNodes = argumentNodes; + this.needsConst = needsConst; + this.isConstChecked = false; + } + + @ExplodeLoop + protected final Object invoke(VirtualFrame frame, VmObjectLike owner, Object receiver) { + checkConst(owner); + var method = getMethod(owner); + var args = new Object[2 + argumentNodes.length]; + args[0] = receiver; + args[1] = owner; + frame.setAuxiliarySlot(getMethodSlot(frame), method); + for (var i = 0; i < argumentNodes.length; i++) { + args[2 + i] = argumentNodes[i].executeGeneric(frame); + } + return getCallNode(method, owner).call(args); + } + + private void checkConst(VmObjectLike owner) { + if (!needsConst || isConstChecked) { + return; + } + CompilerDirectives.transferToInterpreterAndInvalidate(); + doCheckConst(owner); + isConstChecked = true; + } + + protected abstract Method getMethod(VmObjectLike owner); + + protected abstract void doCheckConst(VmObjectLike owner); + + protected DirectCallNode getCallNode(Method method, VmObjectLike owner) { + if (callNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + callNode = DirectCallNode.create(method.getCallTarget(getSourceSection(), owner)); + insert(callNode); + } + assert callNode != null; + return callNode; + } +} diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeMethodNode.java index a30432eda..4243b4342 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeMethodNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeMethodNode.java @@ -15,79 +15,31 @@ */ package org.pkl.core.ast.expression.member; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.DirectCallNode; -import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.source.SourceSection; -import org.jspecify.annotations.Nullable; import org.pkl.core.ast.ExpressionNode; -import org.pkl.core.runtime.Identifier; -import org.pkl.core.runtime.VmObjectLike; -/** - * A non-virtual (statically dispatched) method call. - * - *
Subclasses differ only in how they obtain the {@code owner}/{@code receiver} that the method
- * is invoked on: either by walking the frame chain ({@link InvokeLexicalClassMethodNode}, {@link
- * InvokeLexicalObjectMethodNode}), or off of an explicit receiver expression ({@link
- * InvokeQualifiedClassMethodNode}, {@link InvokeQualifiedObjectMethodNode}).
- */
-public abstract sealed class AbstractInvokeMethodNode extends ExpressionNode
- permits AbstractInvokeQualifiedMethodNode, AbstractInvokeLexicalMethodNode {
+public abstract class AbstractInvokeMethodNode extends ExpressionNode {
- protected final Identifier methodName;
- private final boolean needsConst;
- @Children private ExpressionNode[] argumentNodes;
- @Child private @Nullable DirectCallNode callNode;
- @CompilationFinal protected boolean isConstChecked;
+ public static final Object METHOD_FRAME_SLOT_ID =
+ new Object() {
+ @Override
+ public String toString() {
+ return "method";
+ }
+ };
- protected AbstractInvokeMethodNode(
- SourceSection sourceSection,
- Identifier methodName,
- ExpressionNode[] argumentNodes,
- boolean needsConst) {
+ public AbstractInvokeMethodNode(SourceSection sourceSection) {
super(sourceSection);
- this.methodName = methodName;
- this.argumentNodes = argumentNodes;
- this.needsConst = needsConst;
- this.isConstChecked = false;
- }
-
- @ExplodeLoop
- protected final Object invoke(VirtualFrame frame, VmObjectLike owner, Object receiver) {
- checkConst(owner);
- var args = new Object[2 + argumentNodes.length];
- args[0] = receiver;
- args[1] = owner;
- for (var i = 0; i < argumentNodes.length; i++) {
- args[2 + i] = argumentNodes[i].executeGeneric(frame);
- }
- return getCallNode(owner).call(args);
}
- private void checkConst(VmObjectLike owner) {
- if (!needsConst || isConstChecked) {
- return;
- }
+ protected int getMethodSlot(VirtualFrame frame) {
+ // can't store the slot id as this node may be called from different root nodes
+ // (see constraints14 snippet)
+ var customThisSlot = frame.getFrameDescriptor().getAuxiliarySlots().get(METHOD_FRAME_SLOT_ID);
+ if (customThisSlot != null) return customThisSlot;
CompilerDirectives.transferToInterpreterAndInvalidate();
- doCheckConst(owner);
- isConstChecked = true;
- }
-
- protected abstract CallTarget getCallTarget(VmObjectLike owner);
-
- protected abstract void doCheckConst(VmObjectLike owner);
-
- protected DirectCallNode getCallNode(VmObjectLike owner) {
- if (callNode == null) {
- CompilerDirectives.transferToInterpreterAndInvalidate();
- callNode = DirectCallNode.create(getCallTarget(owner));
- insert(callNode);
- }
- assert callNode != null;
- return callNode;
+ return frame.getFrameDescriptor().findOrAddAuxiliarySlot(METHOD_FRAME_SLOT_ID);
}
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeQualifiedMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeQualifiedMethodNode.java
index 4fb3694e4..e86001b43 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeQualifiedMethodNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/AbstractInvokeQualifiedMethodNode.java
@@ -21,7 +21,8 @@
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmTyped;
-public abstract sealed class AbstractInvokeQualifiedMethodNode extends AbstractInvokeMethodNode
+public abstract sealed class AbstractInvokeQualifiedMethodNode
+ extends AbstractInvokeLexicalOrQualifiedMethodNode
permits InvokeQualifiedClassMethodNode, InvokeQualifiedObjectMethodNode {
@Child private ExpressionNode getReceiverNode;
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InferParentWithinMethodArgumentNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InferParentWithinMethodArgumentNode.java
new file mode 100644
index 000000000..f87ca08d1
--- /dev/null
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InferParentWithinMethodArgumentNode.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pkl.core.ast.expression.member;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.source.SourceSection;
+import org.jspecify.annotations.Nullable;
+import org.pkl.core.ast.ExpressionNode;
+import org.pkl.core.ast.member.Method;
+import org.pkl.core.runtime.VmLanguage;
+
+public final class InferParentWithinMethodArgumentNode extends ExpressionNode {
+ private final VmLanguage language;
+ private final int argIndex;
+ @CompilationFinal private @Nullable Object inferredParent;
+
+ public InferParentWithinMethodArgumentNode(
+ SourceSection sourceSection, VmLanguage language, int argIndex) {
+ super(sourceSection);
+ this.language = language;
+ this.argIndex = argIndex;
+ }
+
+ @Override
+ public Object executeGeneric(VirtualFrame frame) {
+ if (inferredParent != null) return inferredParent;
+
+ // remaining code only runs first time this node is executed
+ // (assuming evaluation isn't continued despite errors)
+
+ CompilerDirectives.transferToInterpreter();
+
+ var methodSlot =
+ frame
+ .getFrameDescriptor()
+ .getAuxiliarySlots()
+ .get(AbstractInvokeLexicalOrQualifiedMethodNode.METHOD_FRAME_SLOT_ID);
+ if (methodSlot == null) {
+ // used in intrinsic constructor e.g. pkl.base#List()
+ throw exceptionBuilder().evalError("cannotInferParent").build();
+ }
+
+ var method = (Method) frame.getAuxiliarySlot(methodSlot);
+ if (method == null) {
+ // used in FunctionN.apply()
+ throw exceptionBuilder().evalError("cannotInferParent").build();
+ }
+
+ var parentTypeNode = method.getParameterTypeNode(argIndex);
+ var parameterTypeDefaultValue =
+ parentTypeNode.createDefaultValue(
+ frame, language, method.getHeaderSection(), method.getQualifiedName());
+ if (parameterTypeDefaultValue != null) {
+ inferredParent = parameterTypeDefaultValue;
+ return inferredParent;
+ }
+
+ throw exceptionBuilder().evalError("cannotInferParent").build();
+ }
+}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalClassMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalClassMethodNode.java
index 32e0480c6..3e331bd1d 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalClassMethodNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalClassMethodNode.java
@@ -15,9 +15,9 @@
*/
package org.pkl.core.ast.expression.member;
-import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
+import org.pkl.core.ast.member.Method;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmObjectLike;
@@ -45,9 +45,9 @@ protected void doCheckConst(VmObjectLike owner) {
}
@Override
- protected CallTarget getCallTarget(VmObjectLike owner) {
+ protected Method getMethod(VmObjectLike owner) {
var method = owner.getVmClass().getDeclaredMethod(methodName);
assert method != null;
- return method.getCallTarget(getSourceSection());
+ return method;
}
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalObjectMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalObjectMethodNode.java
index 5040d8c0b..b80518e98 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalObjectMethodNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeLexicalObjectMethodNode.java
@@ -15,10 +15,10 @@
*/
package org.pkl.core.ast.expression.member;
-import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.ast.VmModifier;
+import org.pkl.core.ast.member.Method;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmObjectLike;
@@ -43,9 +43,9 @@ protected void doCheckConst(VmObjectLike owner) {
}
@Override
- protected CallTarget getCallTarget(VmObjectLike owner) {
+ protected Method getMethod(VmObjectLike owner) {
var method = owner.getMember(methodName);
assert method != null && method.isLocal();
- return (CallTarget) method.getCallTarget().call(owner, owner);
+ return method;
}
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodDirectNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodDirectNode.java
index c11d33b29..89561ede3 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodDirectNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodDirectNode.java
@@ -24,7 +24,8 @@
import org.pkl.core.runtime.VmObjectLike;
/** A non-virtual ("direct") method call. Used only for methods on {@code pkl:base}. */
-public final class InvokeMethodDirectNode extends ExpressionNode {
+public final class InvokeMethodDirectNode extends AbstractInvokeMethodNode {
+ private final ClassMethod method;
private final VmObjectLike owner;
@Child private ExpressionNode receiverNode;
@Children private final ExpressionNode[] argumentNodes;
@@ -38,6 +39,7 @@ public InvokeMethodDirectNode(
ExpressionNode[] argumentNodes) {
super(sourceSection);
+ this.method = method;
this.owner = method.getOwner();
this.receiverNode = receiverNode;
this.argumentNodes = argumentNodes;
@@ -51,6 +53,7 @@ public Object executeGeneric(VirtualFrame frame) {
var args = new Object[2 + argumentNodes.length];
args[0] = receiverNode.executeGeneric(frame);
args[1] = owner;
+ frame.setAuxiliarySlot(getMethodSlot(frame), method);
for (var i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodVirtualNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodVirtualNode.java
index 9b7de94c9..333de9b95 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodVirtualNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeMethodVirtualNode.java
@@ -43,7 +43,7 @@
@NodeChild(value = "receiverNode", type = ExpressionNode.class)
@NodeChild(value = "receiverClassNode", type = GetClassNode.class, executeWith = "receiverNode")
@GenerateWrapper
-public abstract class InvokeMethodVirtualNode extends ExpressionNode {
+public abstract class InvokeMethodVirtualNode extends AbstractInvokeMethodNode {
protected final Identifier methodName;
@Children private final ExpressionNode[] argumentNodes;
private final MemberLookupMode lookupMode;
@@ -91,6 +91,7 @@ protected Object evalFunctionCached(
var args = new Object[2 + argumentNodes.length];
args[0] = receiver.getThisValue();
args[1] = receiver;
+ frame.setAuxiliarySlot(getMethodSlot(frame), null);
for (var i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
@@ -110,6 +111,7 @@ protected Object evalFunction(
var args = new Object[2 + argumentNodes.length];
args[0] = receiver.getThisValue();
args[1] = receiver;
+ frame.setAuxiliarySlot(getMethodSlot(frame), null);
for (var i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
@@ -130,6 +132,7 @@ protected Object evalCached(
var args = new Object[2 + argumentNodes.length];
args[0] = receiver;
args[1] = method.getOwner();
+ frame.setAuxiliarySlot(getMethodSlot(frame), method);
for (var i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
@@ -149,6 +152,7 @@ protected Object eval(
var args = new Object[2 + argumentNodes.length];
args[0] = receiver;
args[1] = method.getOwner();
+ frame.setAuxiliarySlot(getMethodSlot(frame), method);
for (var i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedClassMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedClassMethodNode.java
index e739072e7..4cee5e410 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedClassMethodNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedClassMethodNode.java
@@ -15,9 +15,9 @@
*/
package org.pkl.core.ast.expression.member;
-import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
+import org.pkl.core.ast.member.Method;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmObjectLike;
@@ -42,9 +42,9 @@ protected void doCheckConst(VmObjectLike owner) {
}
@Override
- protected CallTarget getCallTarget(VmObjectLike owner) {
+ protected Method getMethod(VmObjectLike owner) {
var method = owner.getVmClass().getDeclaredMethod(methodName);
assert method != null;
- return method.getCallTarget(getSourceSection());
+ return method;
}
}
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedObjectMethodNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedObjectMethodNode.java
index e31849907..a2e6ced81 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedObjectMethodNode.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeQualifiedObjectMethodNode.java
@@ -15,10 +15,10 @@
*/
package org.pkl.core.ast.expression.member;
-import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.ast.VmModifier;
+import org.pkl.core.ast.member.Method;
import org.pkl.core.runtime.Identifier;
import org.pkl.core.runtime.VmObjectLike;
@@ -43,9 +43,9 @@ protected void doCheckConst(VmObjectLike owner) {
}
@Override
- protected CallTarget getCallTarget(VmObjectLike owner) {
+ protected Method getMethod(VmObjectLike owner) {
var method = owner.getMember(methodName);
assert method != null && method.isLocal();
- return (CallTarget) method.getCallTarget().call(owner, owner);
+ return method;
}
}
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 fffc4ed58..ce07caea1 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
@@ -22,13 +22,15 @@
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.source.SourceSection;
+import org.jspecify.annotations.NonNull;
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.VmTyped;
import org.pkl.core.runtime.VmUtils;
-public abstract class InvokeSuperMethodNode extends ExpressionNode {
+public abstract class InvokeSuperMethodNode extends AbstractInvokeMethodNode {
private final Identifier methodName;
@Children private final ExpressionNode[] argumentNodes;
private final boolean needsConst;
@@ -57,7 +59,8 @@ protected Object eval(
var args = new Object[2 + argumentNodes.length];
args[0] = VmUtils.getReceiverOrNull(frame);
- args[1] = supermethod.getOwner();
+ args[1] = getOwner(supermethod);
+ frame.setAuxiliarySlot(getMethodSlot(frame), supermethod);
for (int i = 0; i < argumentNodes.length; i++) {
args[2 + i] = argumentNodes[i].executeGeneric(frame);
}
@@ -65,6 +68,10 @@ protected Object eval(
return callNode.call(args);
}
+ private static @NonNull VmTyped getOwner(ClassMethod supermethod) {
+ return supermethod.getOwner();
+ }
+
protected ClassMethod findSupermethod(VirtualFrame frame) {
var owner = VmUtils.getOwner(frame);
while (owner instanceof VmFunction) {
diff --git a/pkl-core/src/main/java/org/pkl/core/ast/member/ClassMethod.java b/pkl-core/src/main/java/org/pkl/core/ast/member/ClassMethod.java
index fb236f4e6..1559f5e23 100644
--- a/pkl-core/src/main/java/org/pkl/core/ast/member/ClassMethod.java
+++ b/pkl-core/src/main/java/org/pkl/core/ast/member/ClassMethod.java
@@ -28,7 +28,7 @@
import org.pkl.core.runtime.*;
import org.pkl.core.util.LateInit;
-public final class ClassMethod extends ClassMember {
+public final class ClassMethod extends ClassMember implements Method {
private final List