-
Notifications
You must be signed in to change notification settings - Fork 323
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Accept Array-like objects seamlessly in builtins (#3817)
Most of the time, rather than defining the type of the parameter of the builtin, we want to accept every Array-like object i.e. Vector, Array, polyglot Array etc. Rather than writing all possible combinations, and likely causing bugs on the way anyway as we already saw, one should use `CoerceArrayNode` to convert to Java's `Object[]`. Added various test cases to illustrate the problem.
- Loading branch information
Showing
13 changed files
with
234 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 20 additions & 5 deletions
25
...rc/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InvokeNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 14 additions & 4 deletions
18
.../src/main/java/org/enso/interpreter/node/expression/builtin/meta/NewAtomInstanceNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,27 @@ | ||
package org.enso.interpreter.node.expression.builtin.meta; | ||
|
||
import com.oracle.truffle.api.dsl.Cached; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.nodes.Node; | ||
import org.enso.interpreter.dsl.BuiltinMethod; | ||
import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; | ||
import org.enso.interpreter.runtime.callable.atom.Atom; | ||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor; | ||
import org.enso.interpreter.runtime.data.Array; | ||
|
||
@BuiltinMethod( | ||
type = "Meta", | ||
name = "new_atom", | ||
description = "Creates a new atom with given constructor and fields.") | ||
public class NewAtomInstanceNode extends Node { | ||
Atom execute(AtomConstructor constructor, Array fields) { | ||
return constructor.newInstance(fields.getItems()); | ||
public abstract class NewAtomInstanceNode extends Node { | ||
|
||
static NewAtomInstanceNode build() { | ||
return NewAtomInstanceNodeGen.create(); | ||
} | ||
|
||
abstract Atom execute(AtomConstructor constructor, Object fields); | ||
|
||
@Specialization | ||
Atom doExecute(AtomConstructor constructor, Object fields, @Cached CoerceArrayNode coerce) { | ||
return constructor.newInstance(coerce.execute(fields)); | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
...e/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CoerceArrayNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.enso.interpreter.node.expression.builtin.mutable; | ||
|
||
import com.oracle.truffle.api.dsl.Cached; | ||
import com.oracle.truffle.api.dsl.Fallback; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.interop.InteropLibrary; | ||
import com.oracle.truffle.api.interop.InvalidArrayIndexException; | ||
import com.oracle.truffle.api.interop.UnsupportedMessageException; | ||
import com.oracle.truffle.api.library.CachedLibrary; | ||
import com.oracle.truffle.api.nodes.ExplodeLoop; | ||
import com.oracle.truffle.api.nodes.Node; | ||
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; | ||
import org.enso.interpreter.runtime.Context; | ||
import org.enso.interpreter.runtime.builtin.Builtins; | ||
import org.enso.interpreter.runtime.callable.atom.Atom; | ||
import org.enso.interpreter.runtime.data.Vector; | ||
import org.enso.interpreter.runtime.data.Array; | ||
import org.enso.interpreter.runtime.error.PanicException; | ||
|
||
public abstract class CoerceArrayNode extends Node { | ||
private @Child InteropLibrary library = InteropLibrary.getFactory().createDispatched(10); | ||
|
||
public static CoerceArrayNode build() { | ||
return CoerceArrayNodeGen.create(); | ||
} | ||
|
||
public abstract Object[] execute(Object value); | ||
|
||
@Specialization | ||
Object[] doArray(Array arr) { | ||
return arr.getItems(); | ||
} | ||
|
||
@Specialization | ||
Object[] doVector(Vector arr, @Cached HostValueToEnsoNode hostValueToEnsoNode) { | ||
try { | ||
return convertToArray(arr, hostValueToEnsoNode); | ||
} catch (UnsupportedMessageException e) { | ||
Builtins builtins = Context.get(this).getBuiltins(); | ||
Atom err = builtins.error().makeTypeError(builtins.array(), arr, "arr"); | ||
throw new PanicException(err, this); | ||
} catch (InvalidArrayIndexException e) { | ||
Builtins builtins = Context.get(this).getBuiltins(); | ||
throw new PanicException( | ||
builtins.error().makeInvalidArrayIndexError(arr, e.getInvalidIndex()), this); | ||
} | ||
} | ||
|
||
@Specialization(guards = "interop.hasArrayElements(arr)") | ||
Object[] doArrayLike( | ||
Object arr, | ||
@CachedLibrary(limit = "5") InteropLibrary interop, | ||
@Cached HostValueToEnsoNode hostValueToEnsoNode) { | ||
try { | ||
return convertToArray(arr, hostValueToEnsoNode); | ||
} catch (UnsupportedMessageException e) { | ||
Builtins builtins = Context.get(this).getBuiltins(); | ||
Atom err = builtins.error().makeTypeError(builtins.array(), arr, "arr"); | ||
throw new PanicException(err, this); | ||
} catch (InvalidArrayIndexException e) { | ||
Builtins builtins = Context.get(this).getBuiltins(); | ||
throw new PanicException( | ||
builtins.error().makeInvalidArrayIndexError(arr, e.getInvalidIndex()), this); | ||
} | ||
} | ||
|
||
private Object[] convertToArray(Object arr, HostValueToEnsoNode hostValueToEnsoNode) | ||
throws UnsupportedMessageException, InvalidArrayIndexException { | ||
int argsLength = (int) library.getArraySize(arr); | ||
Object[] arr1 = new Object[argsLength]; | ||
for (int i = 0; i < argsLength; i++) { | ||
arr1[i] = hostValueToEnsoNode.execute(library.readArrayElement(arr, i)); | ||
} | ||
return arr1; | ||
} | ||
|
||
@Fallback | ||
Object[] doOther(Object arr) { | ||
Builtins builtins = Context.get(this).getBuiltins(); | ||
Atom error = builtins.error().makeTypeError("array", arr, "arr"); | ||
throw new PanicException(error, this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from Standard.Base import all | ||
|
||
from Standard.Test import Test, Test_Suite | ||
|
||
polyglot java import java.time.LocalDate | ||
polyglot java import java.lang.String | ||
polyglot java import java.util.function.Function | ||
|
||
spec = Test.group "Polyglot" <| | ||
Test.specify "should be able to invoke a polyglot method by name and pass arguments" <| | ||
poly_date = LocalDate.now | ||
date = Date.now.to_date_time | ||
|
||
Polyglot.invoke poly_date "atStartOfDay" [] . should_equal date | ||
Polyglot.invoke poly_date "atStartOfDay" [].to_array . should_equal date | ||
|
||
Test.specify "should be able to create a new polyglot object using the constructor" <| | ||
Polyglot.new String ["42"] . should_equal "42" | ||
Polyglot.new String ["42"].to_array . should_equal "42" | ||
|
||
Test.specify "should be able to execute a polyglot function object along with corresponding arguments" <| | ||
fun = Function.identity | ||
Polyglot.execute fun ["42"] . should_equal "42" | ||
Polyglot.execute fun ["42"].to_array . should_equal "42" | ||
|
||
main = Test_Suite.run_main spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.