Repository: apple/pkl
File: pkl-core/src/main/java/org/pkl/core/ast/expression/member/InvokeSuperMethodNode.java (Java)

Code before:
    this.argumentNodes = argumentNodes;
  }

  @ExplodeLoop
  @Specialization
  protected Object eval(
      VirtualFrame frame,
      @Cached(value = "findSupermethod(frame)", neverDefault = true) ClassMethod supermethod,
      @Cached("create(supermethod.getCallTarget(sourceSection))") DirectCallNode callNode) {

    var args = new Object[2 + argumentNodes.length];
    args[0] = VmUtils.getReceiverOrNull(frame);
    args[1] = supermethod.getOwner();
    for (int i = 0; i < argumentNodes.length; i++) {
      args[2 + i] = argumentNodes[i].executeGeneric(frame);
    }

    return callNode.call(args);
  }

  protected ClassMethod findSupermethod(VirtualFrame frame) {
    var owner = VmUtils.getOwner(frame);
    while (owner instanceof org.pkl.core.runtime.VmFunction) {
      owner = owner.getEnclosingOwner();
    }
    assert owner.isPrototype();

    var superclass = owner.getVmClass().getSuperclass();
    assert superclass != null;

    // note the use of getMethod() rather than getDeclaredMethod()
    var supermethod = superclass.getMethod(methodName);
    if (supermethod != null) {
      if (needsConst && !supermethod.isConst()) {
        CompilerDirectives.transferToInterpreter();
        throw exceptionBuilder().evalError("methodMustBeConst", methodName.toString()).build();
      }
      return supermethod;
    }

    CompilerDirectives.transferToInterpreter();
    var parent = owner.getParent();
    assert parent != null;
    throw exceptionBuilder()
        .cannotFindMethod(parent, methodName, argumentNodes.length, false)
        .build();
  }
}


Review comment (suggestion):
```suggestion
    }
    assert owner != null : "VmFunction always has a parent";
```

Code after:
    this.methodName = methodName;
    this.argumentNodes = argumentNodes;
  }

  @ExplodeLoop
  @Specialization
  protected Object eval(
      VirtualFrame frame,
      @Cached(value = "findSupermethod(frame)", neverDefault = true) ClassMethod supermethod,
      @Cached("create(supermethod.getCallTarget(sourceSection))") DirectCallNode callNode) {

    var args = new Object[2 + argumentNodes.length];
    args[0] = VmUtils.getReceiverOrNull(frame);
    args[1] = supermethod.getOwner();
    for (int i = 0; i < argumentNodes.length; i++) {
      args[2 + i] = argumentNodes[i].executeGeneric(frame);
    }

    return callNode.call(args);
  }

  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();
    assert superclass != null;

    // note the use of getMethod() rather than getDeclaredMethod()
    var supermethod = superclass.getMethod(methodName);
    if (supermethod != null) {
      if (needsConst && !supermethod.isConst()) {
        CompilerDirectives.transferToInterpreter();
        throw exceptionBuilder().evalError("methodMustBeConst", methodName.toString()).build();
      }
      return supermethod;
    }

    CompilerDirectives.transferToInterpreter();
    var parent = owner.getParent();
    assert parent != null;
    throw exceptionBuilder()
        .cannotFindMethod(parent, methodName, argumentNodes.length, false)
        .build();
  }
}