graal icon indicating copy to clipboard operation
graal copied to clipboard

Espresso interop differs from Truffle Host Interop when there are overloaded methods

Open JaroslavTulach opened this issue 3 years ago • 2 comments

Feature request

Enso language heavily depends on Truflle/Java interop. So far we are using host interop and we are 95% happy with it. However we are also investigating usage of Espresso in parallel. We'd like to switch between the JVM (with host interop) and NI (with Espresso) mode smoothly.

To allow smoth switching between host interop and Espresso interop it is desirable to have a mode where both these interops work the same.

Additional context.

We are ready to donate test cases to provide isolated examples where the interops differ. Here is the first one:


import java.util.concurrent.Executors;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class Espressotest {
    public static void main(String[] args) {
        var ctx = Context.newBuilder("java")
            .option("java.PolyglotInterfaceMappings", "java.lang.Runnable")
            .option("java.Polyglot", "true")
            .allowAllAccess(true)
            .build();
        compareStringParsing(ctx);
    }

    private static void compareStringParsing(Context ctx) {
        var v1 = parseStringHostInterop(ctx.asValue(Integer.class), "456");
        var intClass = ctx.getBindings("java").getMember("java.lang.Integer");
        var v2 = parseStringEspresso(intClass, "456");
        System.err.println("parsed as " + v1 + " in JVM and as " + v2 + " in Espresso");
    }
    
    private static int parseStringHostInterop(Value intClass, String text) {
        return intClass.getMember("static").invokeMember("valueOf", text).asInt();
    }

    private static int parseStringEspresso(Value intClass, String text) {
        return intClass.getMember("static").invokeMember("valueOf/(Ljava/lang/String;)Ljava/lang/Integer;", text).asInt();
    }
}

The parseStringEspresso method has to specify exact signature in this case. That's different to parseStringHostInterop. Ideally the parseStringHostInterop works for both - the host interop as well as Espresso interop.

At the end the exact logic of OverloadedMethod should be copied to Espresso. Only then it is going to be guaranteed the same overload is selected by both interops...

JaroslavTulach avatar Sep 13 '22 12:09 JaroslavTulach

@JaroslavTulach is this issue still relevant? I see you mentioned it was fixed in #4954

oubidar-Abderrahim avatar Sep 16 '22 15:09 oubidar-Abderrahim

@JaroslavTulach is this issue still relevant? I see you mentioned it was fixed in #4954

This issue shall be addressed once #4954 is merged. Right now it is still open.

JaroslavTulach avatar Sep 17 '22 08:09 JaroslavTulach

#4954 has been integrated and the string parsing example with parseStringHostInterop is fixed. However, a program that uses System.out.println still doesn't work:

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class Espressotest {
    public static void main(String[] args) {
        var ctx = Context.newBuilder("java")
            .option("java.PolyglotInterfaceMappings", "java.lang.Runnable")
            .option("java.Polyglot", "true")
            .allowAllAccess(true)
            .build();
        compareSystemOutPrintln(ctx);
    }

    private static void compareSystemOutPrintln(Context ctx) {
        systemOutPrintln(ctx.asValue(System.class), "456");
        var systemClass = ctx.getBindings("java").getMember("java.lang.System");
        systemOutPrintln(systemClass, "456");
    }
    
    private static void systemOutPrintln(Value systemClass, String text) {
        systemClass.getMember("static").getMember("out").invokeMember("println", text);
    }
}

also noted as a comment in the above PR.

JaroslavTulach avatar Oct 06 '22 07:10 JaroslavTulach