Open aitorhh opened 4 years ago
Tracking internally as Issue GR-23079.
Hey @aitorhh . Thank you very much for the report!
We want to to improve Scala support. Would you mind describing what you mean by " The data conversions between Graal <-> Java <-> Scala are not trivial. " by providing a few examples?
In the meantime I suggest you implement converters to ProxyObject / ProxyArray for Scala objects that you pass in with the behavior you desire.
Hi @chumer, sorry for my late reply. I am taking the issue again.
To begin with, for the "graal" -> "java" I use the following example (in scala):
object RuntimeGraalTestAsMain{
def main(args: Array[String]): Unit = {
import org.scalatest.Assertions._
val context = Context.newBuilder()
.allowAllAccess(true)
.build()
assert(context.eval("js", "undefined").as(classOf[Object]) == null)
assert(context.eval("js", "'foobar'").as(classOf[String]) == "foobar")
assert(context.eval("js", "42").as(classOf[Integer]) == 42)
assert(context.eval("js", "{foo:'bar'}").as(classOf[java.util.Map[String, String]]).get("foo") == "bar")
assert(context.eval("js", "[42]").as(classOf[java.util.List[Integer]]).get(0) == 42)
}
}
Without going into more complicated examples the above, is already failing:
Exception in thread "main" java.lang.ClassCastException: Cannot convert 'bar'(language: JavaScript, type: string) to Java type 'java.util.Map': Unsupported target type.
at org.graalvm.truffle/com.oracle.truffle.polyglot.HostInteropErrors.newClassCastException(HostInteropErrors.java:195)
at org.graalvm.truffle/com.oracle.truffle.polyglot.HostInteropErrors.cannotConvertPrimitive(HostInteropErrors.java:66)
at org.graalvm.truffle/com.oracle.truffle.polyglot.ToHostNode.convertImpl(ToHostNode.java:215)
at org.graalvm.truffle/com.oracle.truffle.polyglot.ToHostNode.doGeneric(ToHostNode.java:128)
at org.graalvm.truffle/com.oracle.truffle.polyglot.ToHostNodeGen$Uncached.execute(ToHostNodeGen.java:250)
at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotValue$PrimitiveValue.as(PolyglotValue.java:2134)
at org.graalvm.sdk/org.graalvm.polyglot.Value.as(Value.java:974)
at iot.cluster.RuntimeGraalTest$.main(RuntimeGraalTest.scala:188)
at iot.cluster.RuntimeGraalTest.main(RuntimeGraalTest.scala)
For the "scala" -> "graal", here is an example (of course, this does not compile as is):
object RuntimeGraalTestAsMain{
def main(args: Array[String]): Unit = {
import org.scalatest.Assertions._
val context = Context.newBuilder()
.allowAllAccess(true)
.build()
val executeFunction = "x => {return x;}"
val source = Source
.newBuilder("js", executeFunction.toCharArray, "inline.js")
.build()
val function = context.eval(source)
assert(function.execute(null) == "undefined")
assert(function.execute("foobar") == "foobar")
assert(function.execute(42) == 42)
assert(function.execute(Map[String, String]("foo" -> "bar")) == Map[String, String]("foo" -> "bar"))
assert(function.execute(List(Map[String, String]("foo" -> "bar"))) == List(Map[String, String]("foo" -> "bar")))
assert(function.execute(List(42)) == List(42))
}
}
I will look into the ProxyObject
and ProxyArray
. I complete missed that interface before :)
Feature request
Is your feature request related to a problem? Please describe. The problem is when trying to use graal sdk library withing Scala code. The data conversions between Graal <-> Java <-> Scala are not trivial. Or I am missing something?
Describe the solution you'd like.
I would like to have specific functions to convert
org.graalvm.polyglot.Value
to the Scala primitives and/or collections. At the moment, we can only see "asHostInstance" (https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html), which do not apply properly to Scala.Describe who do you think will benefit the most. GraalVM Polyglot developers and developers of libraries and frameworks depending on Graal.
Describe alternatives you've considered. Looking into possibilities around
And if reflect could help: