crowlogic / arb4j

arb4j is a Java API for the arbitrary precision ball arithmetic library found at http://arblib.org
Other
1 stars 0 forks source link

testLommelPolynomials: fix IncompatibleClassChangeError where the interface method Function.evaluate is expected #416

Closed crowlogic closed 2 months ago

crowlogic commented 2 months ago
  public void declareFunctionReference(ClassVisitor classVisitor, String name, FunctionMapping<?, ?, ?> function)
  {
    String descriptor = "L" + function.name + ";";
    classVisitor.visitField(ACC_PUBLIC
                  | (function.name.equals(functionName) ? 0 : ACC_FINAL), name, descriptor, null, null);
  }

Upon examining the decompiled bytecode of the Q class, I can see that the issue lies in the evaluate method. Here's the relevant part:

ALOAD 0
GETFIELD Q.P : Larb/functions/polynomials/LommelPolynomials;
ALOAD 1
CHECKCAST arb/Integer
ALOAD 0
GETFIELD Q.cℤ1 : Larb/Integer;
ILOAD 3
ALOAD 0
GETFIELD Q.ℤ5 : Larb/Integer;
INVOKEVIRTUAL arb/Integer.sub (Larb/Integer;ILarb/Integer;)Larb/Integer;
ILOAD 2
ILOAD 3
ALOAD 0
GETFIELD Q.Xℝ3 : Larb/RealPolynomial;
INVOKEINTERFACE arb/functions/polynomials/LommelPolynomials.evaluate (Ljava/lang/Object;IILjava/lang/Object;)Ljava/lang/Object; (itf)
CHECKCAST arb/RealPolynomial

The bytecode is attempting to invoke the evaluate method on the P field of type Larb/functions/polynomials/LommelPolynomials using INVOKEINTERFACE. This indicates that LommelPolynomials is expected to be an interface.

However, based on the error message and the code you provided earlier, LommelPolynomials is actually a concrete class that extends RealRecurrentlyGeneratedOrthogonalPolynomialSequence and implements Concept.

To resolve this issue, you need to ensure that the bytecode generation process treats LommelPolynomials as a class and not an interface. Instead of using INVOKEINTERFACE, it should use INVOKEVIRTUAL to invoke the evaluate method on the LommelPolynomials class.

Here's how the corrected bytecode should look:

ALOAD 0
GETFIELD Q.P : Larb/functions/polynomials/LommelPolynomials;
ALOAD 1
CHECKCAST arb/Integer
ALOAD 0
GETFIELD Q.cℤ1 : Larb/Integer;
ILOAD 3
ALOAD 0
GETFIELD Q.ℤ5 : Larb/Integer;
INVOKEVIRTUAL arb/Integer.sub (Larb/Integer;ILarb/Integer;)Larb/Integer;
ILOAD 2
ILOAD 3
ALOAD 0
GETFIELD Q.Xℝ3 : Larb/RealPolynomial;
INVOKEVIRTUAL arb/functions/polynomials/LommelPolynomials.evaluate (Ljava/lang/Object;IILjava/lang/Object;)Ljava/lang/Object;
CHECKCAST arb/RealPolynomial

You'll need to modify the code generation process to use INVOKEVIRTUAL instead of INVOKEINTERFACE when invoking methods on the LommelPolynomials class.

Additionally, ensure that the P field is properly initialized with an instance of the LommelPolynomials class before invoking the evaluate method on it.

By making these changes, the bytecode should correctly recognize LommelPolynomials as a class and invoke its methods using INVOKEVIRTUAL, resolving the IncompatibleClassChangeError.