Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integer types should be converted to unified integer type (long) for java module function calls #369

Closed
beleon opened this issue Mar 27, 2021 · 10 comments

Comments

@beleon
Copy link

beleon commented Mar 27, 2021

Given a Java module

@Import(ns="print")
public class PrintModule {
    public static void print(Float value) {
        System.out.println("float: " + value);
    }
    public static void print(Long value) {
        System.out.println("long: " + value);
    }
    public static void print(String value) {
        System.out.println("str: " + value);
    }
}

the following problem occurs:

bindings.put("x", 10)
engine.eval("p=require('print');print.print(x);print.print(10);")

will result in java.lang.ClassCastException: Cannot cast java.lang.Integer to java.lang.Long because variable x is a Java Integer.
we could try to add a method to the PrintModule:

    public static void print(Integer value) {
        System.out.println("int: " + value);
    }

but this will now result in java.lang.ClassCastException: Cannot cast java.lang.Long to java.lang.Integer because the second print.print call is done with a 10 inside Aviator which is a long. Even though we provided a definition for print(Long value) this definition is ignored, as Aviator consider int and long to be the same type and therefore Aviator picks print(Integer value) over print(Long value).

I think it would be best to automatically convert all integer types (byte, short, int, ...) to the unified integer type long before calling a java module function. This would be analogous to converting all integer types to long when doing arithmetic, e.g.

engine.eval("x*x")

will result in a long even if x is a Java Integer. I think the same conversion should be done when calling a java module function.

@killme2008
Copy link
Owner

The x is passed by yourself, you should take care it by yourself too.

Change the binding type is a simple solution bindings.put("x", 10L).

@beleon
Copy link
Author

beleon commented Mar 27, 2021

While this is true for simple bindings.put("x", 10L) this does not work when inserting a complex Object. E.g. if using a library which you cannot change which has a Class

public class Example {
    private int x = 2;
    public int getX() {
        return x;
    }
}

now if we put bindings.put("x", new Example()) and call engine.eval("p=require('print');print.print(x.getX());") we cannot simply change the type of getX(). I think an automatic conversion would be best, but I'll close the issue if you disagree.

@beleon
Copy link
Author

beleon commented Mar 27, 2021

I know this could be solved by using engine.eval("p=require('print');print.print(x.getX() * 1);") but I think it would benefit the language if this wouldn't be a caveat but simply be solved by the language automatically. :)

@killme2008
Copy link
Owner

@beleon you can use long(x) function to covert a value into aviator long type.

But you are right, maybe the engine can take care of it to simplify the usage. I will consider it in next release, thanks.

@beleon
Copy link
Author

beleon commented Mar 29, 2021

Right, that would be cleaner. Thanks for considering it!

@beleon
Copy link
Author

beleon commented Mar 29, 2021

A somewhat related issue I noticed is that when calling an overloaded function (like the print function in the PrintModule class) with nil, that depending on which types of overloaded functions are defined different methods will be called, e.g. if we define the three methods of the example (public static void print(Float value), public static void print(Long value), public static void print(String value)) calling print.print(nil) from Aviator will invoke the method public static void print(String value). But if we only define public static void print(Float value) and public static void print(Long value) the method with Long will be called. As the 'correct' type for nil cannot be known, maybe nil could be cast to Object when invoking a function call, to avoid different behavior depending on which methods are implemented. Then one could provide a definition for public static void print(Object value) and make a null check there instead of adding a null check to every print-method. Just an idea.

@beleon
Copy link
Author

beleon commented Mar 29, 2021

Then again, this would probably mess with normal methods that are not overloaded, so this is probably not a good idea after all.

@killme2008
Copy link
Owner

@beleon Release 5.2.5 https://github.com/killme2008/aviatorscript/releases/tag/aviator-5.2.5

I may add cast operator to solve the problem you descrbe in latest reply.

@beleon
Copy link
Author

beleon commented Apr 9, 2021

Thank you! I'll test it soon. Adding a cast operator sound like a good solution.

@beleon
Copy link
Author

beleon commented Apr 12, 2021

Can verify that it works 👍 closing the issue

@beleon beleon closed this as completed Apr 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants