diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso index 34d0f52a4eff..301057ea0b80 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso @@ -18,6 +18,7 @@ import project.Errors.Unimplemented.Unimplemented import project.Meta import project.Nothing.Nothing import project.Panic.Panic +import project.Internal.Array_Like_Helpers from project.Data.Boolean import Boolean, False, True from project.Data.Index_Sub_Range import Index_Sub_Range from project.Data.Range.Extensions import all @@ -42,7 +43,7 @@ type Array [1, 2, 3].to_array.at -1 == 3 at : Integer -> Any ! Index_Out_Of_Bounds - at self index = @Builtin_Method "Array.at" + at self index = Array_Like_Helpers.at self index ## Returns the number of elements stored in this array. @@ -51,7 +52,7 @@ type Array [1, 2, 3, 4].to_array.length length : Integer - length self = @Builtin_Method "Array.length" + length self = Array_Like_Helpers.length self ## Identity. This method is implemented purely for completeness with the runtime's diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array_Proxy.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array_Proxy.enso index da0f8d37052e..a100bad8655b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array_Proxy.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array_Proxy.enso @@ -3,6 +3,8 @@ import project.Data.Array.Array import project.Data.Numbers.Integer import project.Errors.Illegal_Argument.Illegal_Argument +import project.Internal.Array_Like_Helpers + ## PRIVATE A helper type used for creating an array from a length and a callback providing its elements. @@ -12,8 +14,10 @@ import project.Errors.Illegal_Argument.Illegal_Argument type returned from polyglot calls to other languages. The most common use-case for it is to pass it to `Vector.from_polyglot_array` to create a vector backed by such custom storage. -@Builtin_Type type Array_Proxy + ## PRIVATE + Value ignore + ## PRIVATE ADVANCED Creates a new `Array_Proxy` from a length and a callback. @@ -28,16 +32,7 @@ type Array_Proxy Vector.from_polyglot_array (Array_Proxy.new 10000000 (i -> i)) new : Integer -> (Integer -> Any) -> Array new length at = Illegal_Argument.handle_java_exception <| - Array_Proxy.new_builtin length at - - ## PRIVATE - The builtin cannot throw `Illegal_Argument` as that type cannot be a - builtin, because they do not support default arguments in constructors. - So a wrapper is used which will translate a Java exception into the Enso - one. This indirection may be removed once the following story is done: - https://www.pivotaltracker.com/n/projects/2539304/stories/183817602 - new_builtin : Integer -> (Integer -> Any) -> Array - new_builtin length at = @Builtin_Method "Array_Proxy.new_builtin" + Array_Like_Helpers.new_array_proxy_builtin length at ## PRIVATE ADVANCED @@ -45,4 +40,4 @@ type Array_Proxy methods. from_proxy_object : Any -> Array from_proxy_object proxy = - Array_Proxy.new proxy.length proxy.at + Array_Like_Helpers.new_array_proxy_builtin proxy.length proxy.at diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso index 67fe2a0b80f0..2b5012ff94fb 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso @@ -23,6 +23,8 @@ import project.Nothing.Nothing import project.Panic.Panic import project.Random import project.Warning.Warning +import project.Internal.Array_Like_Helpers + from project.Data.Boolean import Boolean, False, True from project.Data.Filter_Condition import unify_condition_or_predicate, unify_condition_predicate_or_element from project.Data.Index_Sub_Range import drop_helper, Index_Sub_Range, take_helper @@ -30,7 +32,6 @@ from project.Data.Ordering import all from project.Data.Range.Extensions import all polyglot java import java.lang.IndexOutOfBoundsException -polyglot java import org.enso.base.Array_Builder ## The basic, immutable, vector type. A vector allows to store an arbitrary number of elements, in linear memory. @@ -69,7 +70,7 @@ type Vector a Vector.new my_vec.length (ix -> my_vec.at ix) new : Integer -> (Integer -> Any) -> Vector Any - new length constructor = @Builtin_Method "Vector.new" + new length constructor = Array_Like_Helpers.vector_from_function length constructor ## PRIVATE ADVANCED @@ -161,7 +162,7 @@ type Vector a ## PRIVATE ADVANCED Copies content of a vector into an Array. - to_array self = @Builtin_Method "Vector.to_array" + to_array self = Array_Like_Helpers.vector_to_array self ## Returns the number of elements stored in this vector. @@ -170,7 +171,7 @@ type Vector a [1, 2, 3, 4].length length : Integer - length self = @Builtin_Method "Vector.length" + length self = Array_Like_Helpers.length self ## Gets an element from the vector at a specified index (0-based). @@ -189,7 +190,7 @@ type Vector a [1, 2, 3].at -1 == 3 at : Integer -> Any ! Index_Out_Of_Bounds - at self index = @Builtin_Method "Vector.at" + at self index = Array_Like_Helpers.at self index ## Gets an element from the vector at a specified index (0-based). If the index is invalid then `if_missing` is returned. @@ -1045,7 +1046,7 @@ type Builder Vector.new_builder new : Integer -> Builder - new (capacity=10) = Builder.Value (Array_Builder.newBuilder capacity) + new (capacity=10) = Builder.Value (Array_Like_Helpers.new_vector_builder capacity) ## Checks if this builder is empty. is_empty : Boolean diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso new file mode 100644 index 000000000000..1d87ea7fa30b --- /dev/null +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso @@ -0,0 +1,22 @@ +import project.Any.Any +import project.Data.Array.Array +import project.Data.Vector.Vector +import project.Data.Numbers.Integer + +new_array_proxy_builtin : Integer -> (Integer -> Any) -> Array +new_array_proxy_builtin length at = @Builtin_Method "Array_Like_Helpers.new_array_proxy_builtin" + +new_vector_builder : Integer -> Any +new_vector_builder capacity = @Builtin_Method "Array_Like_Helpers.new_vector_builder" + +length : (Array | Vector) -> Integer +length array_like = @Builtin_Method "Array_Like_Helpers.length" + +at : (Array | Vector) -> Integer -> Any +at array_like index = @Builtin_Method "Array_Like_Helpers.at" + +vector_to_array : (Vector | Array) -> Array +vector_to_array array_like = @Builtin_Method "Array_Like_Helpers.vector_to_array" + +vector_from_function : Integer -> (Integer -> Any) -> Vector Any +vector_from_function length constructor = @Builtin_Method "Array_Like_Helpers.vector_from_function" diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/Write_Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/Write_Extensions.enso index c4090be90ee5..5ad207099980 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/Write_Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/System/File/Write_Extensions.enso @@ -16,7 +16,7 @@ import project.Warning.Warning from project.Data.Boolean import Boolean, False, True from project.Data.Text.Extensions import all -polyglot java import org.enso.base.Array_Builder +polyglot java import org.enso.base.Array_Utils ## Writes (or appends) the text to the specified file using the supplied encoding. The behavior specified in the `existing_file` parameter will be @@ -98,7 +98,7 @@ Vector.write_bytes : (File|Text) -> Existing_File_Behavior -> File ! Illegal_Arg Vector.write_bytes self path on_existing_file=Existing_File_Behavior.Backup = Panic.catch Unsupported_Argument_Types handler=(_ -> Error.throw (Illegal_Argument.Error "Only Vectors consisting of bytes (integers in the range from -128 to 127) are supported by the `write_bytes` method.")) <| ## Convert to a byte array before writing - and fail early if there is any problem. - byte_array = Array_Builder.ensureByteArray self + byte_array = Array_Utils.ensureByteArray self file = File.new path r = on_existing_file.write file stream-> diff --git a/engine/runtime-language-epb/src/main/java/org/enso/interpreter/epb/node/ReadOnlyArray.java b/engine/runtime-language-epb/src/main/java/org/enso/interpreter/epb/node/ReadOnlyArray.java index 9c5efefa7aa8..770642c33bb6 100644 --- a/engine/runtime-language-epb/src/main/java/org/enso/interpreter/epb/node/ReadOnlyArray.java +++ b/engine/runtime-language-epb/src/main/java/org/enso/interpreter/epb/node/ReadOnlyArray.java @@ -12,8 +12,8 @@ * A primitive boxed array type to be used only in EPB. * *

{@link ReadOnlyArray} is essentially a stripped-down, read-only, version of {@link - * org.enso.interpreter.runtime.data.Array}, used for passing arguments. The latter cannot be used - * in EPB because EPB is a dependency of runtime. + * org.enso.interpreter.runtime.data.vector.Array}, used for passing arguments. The latter cannot be + * used in EPB because EPB is a dependency of runtime. */ @ExportLibrary(InteropLibrary.class) public final class ReadOnlyArray implements TruffleObject { diff --git a/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java b/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java index b1938c0dbdc6..5c5070127dcf 100644 --- a/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java +++ b/engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/semantic/IfVsCaseBenchmarks.java @@ -1,8 +1,6 @@ package org.enso.interpreter.bench.benchmarks.semantic; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Paths; @@ -10,10 +8,10 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; + import org.enso.interpreter.test.TestBase; import org.enso.polyglot.MethodNames.Module; import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.io.IOAccess; import org.openjdk.jmh.annotations.Benchmark; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/FunctionCallInstrumentationNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/FunctionCallInstrumentationNode.java index 4716cd1cec41..d9dec8cde771 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/FunctionCallInstrumentationNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/FunctionCallInstrumentationNode.java @@ -16,12 +16,15 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.source.SourceSection; + import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.tag.IdentifiedTag; import java.util.Arrays; import java.util.UUID; + import org.enso.interpreter.node.ClosureRootNode; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag; /** @@ -56,7 +59,7 @@ public boolean isInstrumentable() { /** A simple value class for function call information. */ @ExportLibrary(InteropLibrary.class) - public static final class FunctionCall implements TruffleObject { + public static final class FunctionCall implements EnsoObject { private final Function function; private final Object state; private final @CompilerDirectives.CompilationFinal(dimensions = 1) Object[] arguments; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/SequenceLiteralNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/SequenceLiteralNode.java index 0cd466e44f81..e05549132479 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/SequenceLiteralNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/SequenceLiteralNode.java @@ -1,8 +1,7 @@ package org.enso.interpreter.node.callable; import org.enso.interpreter.node.ExpressionNode; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicSentinel; import com.oracle.truffle.api.frame.VirtualFrame; @@ -43,6 +42,6 @@ public Object executeGeneric(VirtualFrame frame) { throw sentinel; } } - return Vector.fromArray(new Array(itemValues)); + return ArrayLikeHelpers.asVectorWithCheckAt(itemValues); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/controlflow/caseexpr/BranchResult.java b/engine/runtime/src/main/java/org/enso/interpreter/node/controlflow/caseexpr/BranchResult.java index 05e16408658e..bc881760301e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/controlflow/caseexpr/BranchResult.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/controlflow/caseexpr/BranchResult.java @@ -1,10 +1,11 @@ package org.enso.interpreter.node.controlflow.caseexpr; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; + import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; -record BranchResult(boolean isMatched, Object result) implements TruffleObject { +record BranchResult(boolean isMatched, Object result) implements EnsoObject { static BranchResult failure(Node node) { return new BranchResult(false, EnsoContext.get(node).getBuiltins().nothing()); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/GetAttachedStackTraceNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/GetAttachedStackTraceNode.java index ed64a4093836..4860fddaeaa1 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/GetAttachedStackTraceNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/GetAttachedStackTraceNode.java @@ -6,7 +6,7 @@ import org.enso.interpreter.node.expression.builtin.runtime.GetStackTraceNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -14,7 +14,7 @@ name = "primitive_get_attached_stack_trace", description = "Gets the stack trace attached to the throwable.") public class GetAttachedStackTraceNode extends Node { - Array execute(@AcceptsError Object error) { + EnsoObject execute(@AcceptsError Object error) { if (error instanceof Throwable) { return GetStackTraceNode.stackTraceToArray((Throwable) error); } else { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/AtVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/AtVectorNode.java index a46c761c903c..b583350e2bf1 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/AtVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/AtVectorNode.java @@ -1,43 +1,39 @@ package org.enso.interpreter.node.expression.builtin.immutable; import com.oracle.truffle.api.CompilerDirectives; -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.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Vector; +import org.enso.interpreter.runtime.data.vector.ArrayLikeAtNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; import org.enso.interpreter.runtime.error.DataflowError; -import org.enso.interpreter.runtime.error.WarningsLibrary; @BuiltinMethod( - type = "Vector", + type = "Array_Like_Helpers", name = "at", description = "Returns an element of Vector at the specified index.") public class AtVectorNode extends Node { - private @Child InteropLibrary interop = InteropLibrary.getFactory().createDispatched(3); - private @Child WarningsLibrary warnings = WarningsLibrary.getFactory().createDispatched(3); - private @Child HostValueToEnsoNode convert = HostValueToEnsoNode.build(); + private @Child ArrayLikeAtNode at = ArrayLikeAtNode.create(); + private @Child ArrayLikeLengthNode length; - Object execute(Vector self, long index) { + Object execute(Object arrayLike, long index) { try { - return readElement(self, index); - } catch (UnsupportedMessageException e) { - CompilerDirectives.transferToInterpreter(); - throw new IllegalStateException(e); + long actualIndex = index < 0 ? index + len(arrayLike) : index; + return at.executeAt(arrayLike, actualIndex); + } catch (InvalidArrayIndexException e) { + var len = len(arrayLike); + var ctx = EnsoContext.get(this); + var payload = ctx.getBuiltins().error().makeIndexOutOfBounds(index, len); + return DataflowError.withoutTrace(payload, this); } } - private Object readElement(Vector self, long index) throws UnsupportedMessageException { - try { - long actualIndex = index < 0 ? index + self.length(interop) : index; - return self.readArrayElement(actualIndex, interop, warnings, convert); - } catch (InvalidArrayIndexException e) { - EnsoContext ctx = EnsoContext.get(this); - return DataflowError.withoutTrace( - ctx.getBuiltins().error().makeIndexOutOfBounds(index, self.length(interop)), this); + private long len(Object arrayLike) { + if (length == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + length = insert(ArrayLikeLengthNode.create()); } + return length.executeLength(arrayLike); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java index ca7ef1bd7aed..be1ca6ae8a21 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java @@ -2,20 +2,17 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Cached.Shared; -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.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.mutable.CopyNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeAtNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCopyToArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -28,87 +25,41 @@ static FlattenVectorNode build() { return FlattenVectorNodeGen.create(); } - abstract Vector execute(Object self); + abstract EnsoObject execute(Object self); @Specialization - Vector fromVector( - Vector self, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return flatten(self.toArray(), copyNode, interop); - } catch (UnsupportedMessageException e) { - CompilerDirectives.transferToInterpreter(); - Builtins builtins = EnsoContext.get(this).getBuiltins(); - throw new PanicException( - builtins.error().makeTypeError(builtins.vector(), self, "self"), this); - } - } - - @Specialization - Vector fromArray( - Array self, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return flatten(self, copyNode, interop); - } catch (UnsupportedMessageException e) { - throw unsupportedException(self); - } - } - - @Specialization(guards = "interop.hasArrayElements(self)") - Vector fromArrayLike( + EnsoObject flattenAnything( Object self, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return flatten(self, copyNode, interop); - } catch (UnsupportedMessageException e) { - throw unsupportedException(self); - } + @Cached ArrayLikeCopyToArrayNode copyNode, + @Cached ArrayLikeLengthNode lengthNode, + @Cached ArrayLikeAtNode atNode) { + return flatten(self, copyNode, lengthNode, atNode); } - @Fallback - Vector fromUnknown(Object self) { - throw unsupportedException(self); - } - - private PanicException unsupportedException(Object self) { - CompilerDirectives.transferToInterpreter(); - var ctx = EnsoContext.get(this); - var err = ctx.getBuiltins().error().makeTypeError("polyglot array", self, "self"); - throw new PanicException(err, this); - } - - private Vector flatten(Object storage, CopyNode copyNode, InteropLibrary interop) - throws UnsupportedMessageException { + private EnsoObject flatten( + Object storage, + ArrayLikeCopyToArrayNode copyNode, + ArrayLikeLengthNode lengthNode, + ArrayLikeAtNode atNode) { try { - long length = interop.getArraySize(storage); + long length = lengthNode.executeLength(storage); long flattened_length = 0; for (long i = 0; i < length; i++) { - var item = interop.readArrayElement(storage, i); - if (!interop.hasArrayElements(item)) { - CompilerDirectives.transferToInterpreter(); - Builtins builtins = EnsoContext.get(this).getBuiltins(); - throw new PanicException( - builtins.error().makeTypeError(builtins.vector(), item, "[" + i + "]"), this); - } - - flattened_length += interop.getArraySize(item); + var item = atNode.executeAt(storage, i); + flattened_length += lengthNode.executeLength(item); } - Array result = Array.allocate(flattened_length); + var result = ArrayLikeHelpers.allocate(flattened_length); long current_index = 0; for (long i = 0; i < length; i++) { - var item = interop.readArrayElement(storage, i); - var item_length = interop.getArraySize(item); + var item = atNode.executeAt(storage, i); + var item_length = lengthNode.executeLength(item); copyNode.execute(item, 0, result, current_index, item_length); current_index += item_length; } - return Vector.fromArray(result); + return ArrayLikeHelpers.asVectorFromArray(result); } catch (InvalidArrayIndexException e) { CompilerDirectives.transferToInterpreter(); Builtins builtins = EnsoContext.get(this).getBuiltins(); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromArrayBuiltinVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromArrayBuiltinVectorNode.java index 5ac37fa39d57..34fef9fbc447 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromArrayBuiltinVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromArrayBuiltinVectorNode.java @@ -1,15 +1,13 @@ package org.enso.interpreter.node.expression.builtin.immutable; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.CachedLibrary; +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.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCoerceToArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; @BuiltinMethod( type = "Vector", @@ -21,29 +19,19 @@ static FromArrayBuiltinVectorNode build() { return FromArrayBuiltinVectorNodeGen.create(); } - abstract Vector execute(Object arr); + abstract EnsoObject execute(Object arr); - @Specialization - Vector fromVector(Vector arr) { - return arr; - } - - @Specialization(guards = "interop.hasArrayElements(arr)") - Vector fromArrayLikeObject( - Object arr, - @Cached CoerceArrayNode coerce, - @CachedLibrary(limit = "3") InteropLibrary interop) { - return Vector.fromArray(new Array(coerce.execute(arr))); + @Specialization(guards = "isImmutableArrayLike(arr)") + EnsoObject fromVector(Object arr) { + return (EnsoObject) arr; } @Fallback - Vector fromUnknown(Object arr) { - throw unsupportedException(arr); + EnsoObject fromArrayLikeObject(Object arr, @Cached ArrayLikeCoerceToArrayNode coerce) { + return ArrayLikeHelpers.asVectorWithCheckAt(coerce.execute(arr)); } - private PanicException unsupportedException(Object arr) { - var ctx = EnsoContext.get(this); - var err = ctx.getBuiltins().error().makeTypeError("polyglot array", arr, "array"); - throw new PanicException(err, this); + static boolean isImmutableArrayLike(Object obj) { + return ArrayLikeHelpers.isImmutable(obj); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromPolyglotArrayBuiltinVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromPolyglotArrayBuiltinVectorNode.java index fb8ccb3844cf..ed0c7f91fbe0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromPolyglotArrayBuiltinVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FromPolyglotArrayBuiltinVectorNode.java @@ -6,7 +6,8 @@ import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Vector; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -21,16 +22,16 @@ static FromPolyglotArrayBuiltinVectorNode build() { return FromPolyglotArrayBuiltinVectorNodeGen.create(); } - abstract Vector execute(Object arr); + abstract EnsoObject execute(Object arr); @Specialization(guards = "interop.hasArrayElements(arr)") - Vector doObject(Object arr, @CachedLibrary(limit = "1") InteropLibrary interop) { - return Vector.fromArray(arr); + EnsoObject doObject(Object arr, @CachedLibrary(limit = "1") InteropLibrary interop) { + return ArrayLikeHelpers.asVectorFromArray(arr); } @Fallback - Vector doOther(Object arr) { - EnsoContext ctx = EnsoContext.get(this); + EnsoObject doOther(Object arr) { + var ctx = EnsoContext.get(this); throw new PanicException( ctx.getBuiltins().error().makeTypeError("polyglot array", arr, "array"), this); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java index 58ec218c7575..80a74d9e49e6 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java @@ -1,19 +1,13 @@ package org.enso.interpreter.node.expression.builtin.immutable; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Cached.Shared; -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.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.mutable.CopyNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCopyToArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; @BuiltinMethod( type = "Vector", @@ -25,91 +19,21 @@ static InsertBuiltinVectorNode build() { return InsertBuiltinVectorNodeGen.create(); } - abstract Vector execute(Object vec, long index, Object values); + abstract EnsoObject execute(Object vec, long index, Object values); @Specialization - Vector fromVector( - Vector vec, - long index, - Vector values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec.toArray(), index, values.toArray(), copyNode, interop); - } - - @Specialization - Vector fromArray( - Array vec, - long index, - Vector values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec, index, values.toArray(), copyNode, interop); - } - - @Specialization(guards = "interop.hasArrayElements(vec)") - Vector fromArrayLike( + EnsoObject fromObject( Object vec, long index, - Vector values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec, index, values.toArray(), copyNode, interop); - } - - @Specialization(guards = "interop.hasArrayElements(values)") - Vector fromVectorWithArrayLikeObject( - Vector vec, - long index, Object values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec.toArray(), index, values, copyNode, interop); - } - - @Specialization(guards = "interop.hasArrayElements(values)") - Vector fromArrayWithArrayLikeObject( - Array vec, - long index, - Object values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec, index, values, copyNode, interop); - } - - @Specialization(guards = {"interop.hasArrayElements(vec)", "interop.hasArrayElements(values)"}) - Vector fromArrayLikeWithArrayLikeObject( - Object vec, - long index, - Object values, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - return insertBuiltin(vec, index, values, copyNode, interop); - } - - @Fallback - Vector fromUnknown(Object vec, long index, Object values) { - throw unsupportedException(values); - } - - private PanicException unsupportedException(Object values) { - var ctx = EnsoContext.get(this); - var err = ctx.getBuiltins().error().makeTypeError("polyglot array", values, "values"); - throw new PanicException(err, this); - } - - private Vector insertBuiltin( - Object current, long index, Object values, CopyNode copyNode, InteropLibrary interop) { - try { - long currentLength = interop.getArraySize(current); - long valuesLength = interop.getArraySize(values); - Array result = Array.allocate(currentLength + valuesLength); - copyNode.execute(current, 0, result, 0, index); - copyNode.execute(values, 0, result, index, valuesLength); - copyNode.execute(current, index, result, index + valuesLength, currentLength - index); - return Vector.fromArray(result); - } catch (UnsupportedMessageException e) { - throw unsupportedException(values); - } + @Cached ArrayLikeCopyToArrayNode copyNode, + @Cached ArrayLikeLengthNode lengthNode) { + long currentLength = lengthNode.executeLength(vec); + long valuesLength = lengthNode.executeLength(values); + var result = ArrayLikeHelpers.allocate(currentLength + valuesLength); + copyNode.execute(vec, 0, result, 0, index); + copyNode.execute(values, 0, result, index, valuesLength); + copyNode.execute(vec, index, result, index + valuesLength, currentLength - index); + return ArrayLikeHelpers.asVectorFromArray(result); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/LengthVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/LengthVectorNode.java new file mode 100644 index 000000000000..29c65fea60ec --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/LengthVectorNode.java @@ -0,0 +1,17 @@ +package org.enso.interpreter.node.expression.builtin.immutable; + +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; + +@BuiltinMethod( + type = "Array_Like_Helpers", + name = "length", + description = "Returns the length of this Vector.") +public class LengthVectorNode extends Node { + @Child ArrayLikeLengthNode length = ArrayLikeLengthNode.create(); + + long execute(Object arrayLike) { + return length.executeLength(arrayLike); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java index 0eb966b8fb43..b13185133201 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java @@ -1,21 +1,13 @@ package org.enso.interpreter.node.expression.builtin.immutable; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Cached.Shared; -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.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.mutable.CopyNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCopyToArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; @BuiltinMethod( type = "Vector", @@ -27,69 +19,19 @@ static RemoveAtVectorNode build() { return RemoveAtVectorNodeGen.create(); } - abstract Vector execute(Object vec, long index); + abstract EnsoObject execute(Object vec, long index); @Specialization - Vector fromVector( - Vector vec, + EnsoObject removeAtIndex( + Object storage, long index, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return removeAtIndex(vec.toArray(), index, copyNode, interop); - } catch (UnsupportedMessageException e) { - CompilerDirectives.transferToInterpreter(); - Builtins builtins = EnsoContext.get(this).getBuiltins(); - throw new PanicException(builtins.error().makeTypeError(builtins.vector(), vec, "vec"), this); - } - } - - @Specialization - Vector fromArray( - Array vec, - long index, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return removeAtIndex(vec, index, copyNode, interop); - } catch (UnsupportedMessageException e) { - throw unsupportedException(vec); - } - } - - @Specialization(guards = "interop.hasArrayElements(vec)") - Vector fromArrayLike( - Object vec, - long index, - @Shared("copyNode") @Cached CopyNode copyNode, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - return removeAtIndex(vec, index, copyNode, interop); - } catch (UnsupportedMessageException e) { - throw unsupportedException(vec); - } - } - - @Fallback - Vector fromUnknown(Object vec, long index) { - throw unsupportedException(vec); - } - - private PanicException unsupportedException(Object vec) { - CompilerDirectives.transferToInterpreter(); - var ctx = EnsoContext.get(this); - var err = ctx.getBuiltins().error().makeTypeError("polyglot array", vec, "vec"); - throw new PanicException(err, this); - } - - private Vector removeAtIndex( - Object storage, long index, CopyNode copyArrayNode, InteropLibrary interop) - throws UnsupportedMessageException { - long length = interop.getArraySize(storage); + @Cached ArrayLikeCopyToArrayNode copyArrayNode, + @Cached ArrayLikeLengthNode lengthNode) { + long length = lengthNode.executeLength(storage); long actualIndex = index < 0 ? index + length : index; - Array array = Array.allocate(length - 1); + var array = ArrayLikeHelpers.allocate(length - 1); copyArrayNode.execute(storage, 0, array, 0, actualIndex); copyArrayNode.execute(storage, actualIndex + 1, array, actualIndex, length - actualIndex - 1); - return Vector.fromArray(array); + return ArrayLikeHelpers.asVectorFromArray(array); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java index c6073ba6c46c..adfb29e73c14 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java @@ -1,66 +1,22 @@ package org.enso.interpreter.node.expression.builtin.immutable; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Cached.Shared; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; +import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; @BuiltinMethod(type = "Vector", name = "slice", description = "Returns a slice of this Vector.") -public abstract class SliceArrayVectorNode extends Node { - SliceArrayVectorNode() {} +public final class SliceArrayVectorNode extends Node { + private @Child ArrayLikeLengthNode lengthNode = ArrayLikeLengthNode.create(); - public static SliceArrayVectorNode build() { - return SliceArrayVectorNodeGen.create(); - } - - abstract Object execute(Object self, long start, long end); - - @Specialization - Object sliceArray(Array self, long start, long end) { - return Array.slice(self, start, end, self.length()); - } - - @Specialization - Object sliceVector( - Vector self, - long start, - long end, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary iop) { - try { - return Array.slice(self, start, end, self.length(iop)); - } catch (UnsupportedMessageException ex) { - CompilerDirectives.transferToInterpreter(); - throw unsupportedMessageException(self); - } - } + private SliceArrayVectorNode() {} - @Specialization(replaces = {"sliceArray", "sliceVector"}) - Object sliceArrayLike( - Object self, - long start, - long end, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary iop) { - try { - long len = iop.getArraySize(self); - return Array.slice(self, start, end, len); - } catch (UnsupportedMessageException ex) { - CompilerDirectives.transferToInterpreter(); - throw unsupportedMessageException(self); - } + public static SliceArrayVectorNode build() { + return new SliceArrayVectorNode(); } - private PanicException unsupportedMessageException(Object self) throws PanicException { - var ctx = EnsoContext.get(this); - var arrayType = ctx.getBuiltins().array(); - throw new PanicException( - ctx.getBuiltins().error().makeTypeError(arrayType, self, "self"), this); + Object execute(Object self, long start, long end) { + var len = lengthNode.executeLength(self); + return ArrayLikeHelpers.slice(self, start, end, len); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/ExecuteNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/ExecuteNode.java index a0c4285de7bd..193014c48e0b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/ExecuteNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/ExecuteNode.java @@ -11,7 +11,7 @@ import org.enso.interpreter.Constants; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; -import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCoerceToArrayNode; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -32,7 +32,8 @@ static ExecuteNode build() { abstract Object execute(Object callable, Object arguments); @Specialization - Object doExecute(Object callable, Object arguments, @Cached("build()") CoerceArrayNode coerce) { + Object doExecute( + Object callable, Object arguments, @Cached("build()") ArrayLikeCoerceToArrayNode coerce) { try { return hostValueToEnsoNode.execute(library.execute(callable, coerce.execute(arguments))); } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/GetMembersNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/GetMembersNode.java index c904913d2075..cc1bfbb144f7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/GetMembersNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/GetMembersNode.java @@ -5,7 +5,7 @@ import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.Constants; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; @BuiltinMethod( type = "Polyglot", @@ -20,7 +20,7 @@ Object execute(Object object) { try { return library.getMembers(object); } catch (UnsupportedMessageException e) { - return Array.empty(); + return ArrayLikeHelpers.empty(); } } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InstantiateNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InstantiateNode.java index 011bd4836f7e..08126f82acda 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InstantiateNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InstantiateNode.java @@ -11,7 +11,7 @@ import org.enso.interpreter.Constants; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; -import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCoerceToArrayNode; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -33,7 +33,7 @@ static InstantiateNode build() { @Specialization Object doExecute( - Object constructor, Object arguments, @Cached("build()") CoerceArrayNode coerce) { + Object constructor, Object arguments, @Cached("build()") ArrayLikeCoerceToArrayNode coerce) { try { var value = library.instantiate(constructor, coerce.execute(arguments)); return fromHost.execute(value); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InvokeNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InvokeNode.java index f7ea8dff4405..92a83916d7c9 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InvokeNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/generic/InvokeNode.java @@ -11,8 +11,8 @@ import com.oracle.truffle.api.profiles.BranchProfile; import org.enso.interpreter.Constants; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCoerceToArrayNode; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -34,7 +34,10 @@ static InvokeNode build() { @Specialization Object doExecute( - Object target, Object name, Object arguments, @Cached("build()") CoerceArrayNode coerce) { + Object target, + Object name, + Object arguments, + @Cached("build()") ArrayLikeCoerceToArrayNode coerce) { try { return library.invokeMember( target, expectStringNode.execute(name), coerce.execute(arguments)); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/AtomWithAHoleNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/AtomWithAHoleNode.java index 969f686c0d8b..236c9ff30dea 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/AtomWithAHoleNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/AtomWithAHoleNode.java @@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.callable.atom.StructsLibrary; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; import org.enso.interpreter.runtime.state.State; @@ -76,7 +77,7 @@ Object doExecute( } @ExportLibrary(InteropLibrary.class) - static final class HoleInAtom implements TruffleObject { + static final class HoleInAtom implements EnsoObject { Atom result; int index; Function function; @@ -109,7 +110,7 @@ void init(Atom result, int index, Function function) { } @ExportMessage Object getMembers(boolean includeInternal) { - return new Array("value", "fill"); + return ArrayLikeHelpers.wrapStrings("value", "fill"); } @ExportMessage diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAtomFieldsNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAtomFieldsNode.java index dbca62c9e960..d71402ea0388 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAtomFieldsNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAtomFieldsNode.java @@ -6,7 +6,8 @@ import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.atom.StructsLibrary; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; @BuiltinMethod( type = "Meta", @@ -18,10 +19,10 @@ static GetAtomFieldsNode build() { return GetAtomFieldsNodeGen.create(); } - abstract Array execute(Atom atom); + abstract EnsoObject execute(Atom atom); @Specialization - Array doStruct(Atom atom, @CachedLibrary(limit = "2") StructsLibrary structs) { - return new Array(structs.getFields(atom)); + EnsoObject doStruct(Atom atom, @CachedLibrary(limit = "2") StructsLibrary structs) { + return ArrayLikeHelpers.wrapObjectsWithCheckAt(structs.getFields(atom)); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetConstructorFieldNamesNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetConstructorFieldNamesNode.java index 6ba9f2b7d4e7..65e868b7b249 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetConstructorFieldNamesNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetConstructorFieldNamesNode.java @@ -6,8 +6,9 @@ import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; @BuiltinMethod( type = "Meta", @@ -19,20 +20,20 @@ static GetConstructorFieldNamesNode build() { return GetConstructorFieldNamesNodeGen.create(); } - abstract Array execute(Object obj); + abstract EnsoObject execute(Object obj); @Specialization - final Array fieldNamesForAtomCtor(AtomConstructor atomConstructor) { + final EnsoObject fieldNamesForAtomCtor(AtomConstructor atomConstructor) { ArgumentDefinition[] fields = atomConstructor.getFields(); - Object[] result = new Object[fields.length]; + Text[] result = new Text[fields.length]; for (int i = 0; i < fields.length; i++) { result[i] = Text.create(fields[i].getName()); } - return new Array(result); + return ArrayLikeHelpers.wrapEnsoObjects(result); } @Fallback - final Array fieldNamesForAny(Object any) { - return Array.empty(); + final EnsoObject fieldNamesForAny(Object any) { + return ArrayLikeHelpers.empty(); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeConstructorsNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeConstructorsNode.java index a48d60ca74d4..0aff14588816 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeConstructorsNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeConstructorsNode.java @@ -8,8 +8,9 @@ import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; import org.enso.interpreter.runtime.type.TypesGen; @@ -23,24 +24,24 @@ static GetTypeConstructorsNode build() { return GetTypeConstructorsNodeGen.create(); } - abstract Array execute(Object type, Object factory); + abstract EnsoObject execute(Object type, Object factory); @Specialization @CompilerDirectives.TruffleBoundary - Array allConstructors(Type type, AtomConstructor factory) { + EnsoObject allConstructors(Type type, AtomConstructor factory) { var rawConstructors = type.getConstructors().values(); - var rawResult = new Object[rawConstructors.size()]; + var rawResult = new EnsoObject[rawConstructors.size()]; int at = 0; for (var cons : rawConstructors) { var metaCons = factory.newInstance(cons); rawResult[at++] = metaCons; } - return new Array(rawResult); + return ArrayLikeHelpers.wrapEnsoObjects(rawResult); } @Fallback @CompilerDirectives.TruffleBoundary - Array empty(Object type, Object factory) { + EnsoObject empty(Object type, Object factory) { var ctx = EnsoContext.get(this); var builtins = ctx.getBuiltins(); Atom payload; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeMethodsNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeMethodsNode.java index c52767f966f9..1150c2324c92 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeMethodsNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetTypeMethodsNode.java @@ -7,8 +7,9 @@ import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -21,18 +22,20 @@ static GetTypeMethodsNode build() { return GetTypeMethodsNodeGen.create(); } - abstract Array execute(Object type); + abstract EnsoObject execute(Object type); @Specialization @CompilerDirectives.TruffleBoundary - Array allMethods(Type type) { + EnsoObject allMethods(Type type) { var methods = type.getDefinitionScope().getMethods().get(type); - return methods == null ? Array.empty() : new Array(methods.keySet().toArray()); + return methods == null + ? ArrayLikeHelpers.empty() + : ArrayLikeHelpers.wrapStrings(methods.keySet().toArray(new String[0])); } @Fallback @CompilerDirectives.TruffleBoundary - Array empty(Object type) { + EnsoObject empty(Object type) { var ctx = EnsoContext.get(this); var builtins = ctx.getBuiltins(); Atom payload = builtins.error().makeTypeError("Type", type, "type"); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/NewAtomInstanceNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/NewAtomInstanceNode.java index 43a25eccef3e..9eb92681d69c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/NewAtomInstanceNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/NewAtomInstanceNode.java @@ -4,9 +4,9 @@ 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.vector.ArrayLikeCoerceToArrayNode; @BuiltinMethod( type = "Meta", @@ -22,7 +22,8 @@ static NewAtomInstanceNode build() { abstract Atom execute(AtomConstructor constructor, Object fields); @Specialization - Atom doExecute(AtomConstructor constructor, Object fields, @Cached CoerceArrayNode coerce) { + Atom doExecute( + AtomConstructor constructor, Object fields, @Cached ArrayLikeCoerceToArrayNode coerce) { return constructor.newInstance(coerce.execute(fields)); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayAtNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayAtNode.java deleted file mode 100644 index d26fa6fef67d..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayAtNode.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.mutable; - -import com.oracle.truffle.api.CompilerDirectives; -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.nodes.Node; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.error.DataflowError; - -@BuiltinMethod(type = "Array", name = "at", description = "Get element of a polyglot array") -public class ArrayAtNode extends Node { - @Child InteropLibrary iop = InteropLibrary.getFactory().createDispatched(3); - @Child HostValueToEnsoNode convert = HostValueToEnsoNode.build(); - - Object execute(Object self, long index) { - try { - return readElement(self, index); - } catch (UnsupportedMessageException ex) { - CompilerDirectives.transferToInterpreter(); - throw new IllegalStateException(ex); - } - } - - private Object readElement(Object self, long index) throws UnsupportedMessageException { - try { - long actualIndex = index < 0 ? index + iop.getArraySize(self) : index; - var element = iop.readArrayElement(self, actualIndex); - return convert.execute(element); - } catch (InvalidArrayIndexException e) { - EnsoContext ctx = EnsoContext.get(this); - return DataflowError.withoutTrace( - ctx.getBuiltins().error().makeIndexOutOfBounds(index, iop.getArraySize(self)), this); - } - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayLengthNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayLengthNode.java deleted file mode 100644 index 0a89c4b9542e..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/ArrayLengthNode.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.mutable; - -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.error.PanicException; - -@BuiltinMethod(type = "Array", name = "length", description = "Length of polyglot array") -public class ArrayLengthNode extends Node { - @Child InteropLibrary iop = InteropLibrary.getFactory().createDispatched(3); - - long execute(Object self) { - try { - return iop.getArraySize(self); - } catch (UnsupportedMessageException ex) { - var ctx = EnsoContext.get(this); - var pay = - ctx.getBuiltins() - .error() - .makeUnsupportedArgumentsError(new Object[] {self}, ex.getMessage()); - throw new PanicException(pay, this); - } - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortVectorNode.java index 78bcbaad246d..12f5e1c28208 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/ordering/SortVectorNode.java @@ -11,6 +11,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -20,6 +21,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; + import org.enso.interpreter.dsl.AcceptsError; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.node.callable.dispatch.CallOptimiserNode; @@ -32,11 +34,9 @@ import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.ArrayRope; import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.data.Vector; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.DataflowError; import org.enso.interpreter.runtime.error.PanicException; import org.enso.interpreter.runtime.error.Warning; @@ -248,7 +248,7 @@ Object sortGeneric( } resultVec.addAll(group.elems); } - var sortedVector = Vector.fromArray(new Array(resultVec.toArray())); + var sortedVector = ArrayLikeHelpers.asVectorWithCheckAt(resultVec.toArray()); // Attach gathered warnings along with different comparators warning switch (problemBehavior) { case REPORT_ERROR -> { @@ -290,7 +290,7 @@ Object sortGeneric( private Object sortPrimitiveVector(Object[] elems, DefaultSortComparator javaComparator) throws CompareException { Arrays.sort(elems, javaComparator); - var sortedVector = Vector.fromArray(new Array(elems)); + var sortedVector = ArrayLikeHelpers.asVectorWithCheckAt(elems); if (javaComparator.hasWarnings()) { return attachWarnings(sortedVector, javaComparator.getEncounteredWarnings()); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/runtime/GetStackTraceNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/runtime/GetStackTraceNode.java index 17f1d7ad17a6..183e062ba56b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/runtime/GetStackTraceNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/runtime/GetStackTraceNode.java @@ -5,7 +5,8 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; @BuiltinMethod( @@ -14,17 +15,17 @@ description = "Gets the current execution stacktrace.", autoRegister = false) public class GetStackTraceNode extends Node { - Array execute(VirtualFrame requestOwnStackFrame) { + EnsoObject execute(VirtualFrame requestOwnStackFrame) { var exception = new PanicException("Stacktrace", this); TruffleStackTrace.fillIn(exception); return stackTraceToArray(exception); } @CompilerDirectives.TruffleBoundary - public static Array stackTraceToArray(Throwable exception) { + public static EnsoObject stackTraceToArray(Throwable exception) { var elements = TruffleStackTrace.getStackTrace(exception); if (elements == null) { - return Array.empty(); + return ArrayLikeHelpers.empty(); } int count = 0; for (int i = 0; i < elements.size(); i++) { @@ -42,6 +43,6 @@ public static Array stackTraceToArray(Throwable exception) { } arr[at++] = element.getGuestObject(); } - return new Array(arr); + return ArrayLikeHelpers.wrapObjectsWithCheckAt(arr); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java index e66c5c618319..b9b4b9299ae0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java @@ -1,5 +1,11 @@ package org.enso.interpreter.node.expression.builtin.text.util; +import org.enso.interpreter.node.expression.builtin.meta.TypeOfNode; +import org.enso.interpreter.runtime.callable.atom.Atom; +import org.enso.interpreter.runtime.callable.atom.AtomConstructor; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.type.TypesGen; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.Specialization; @@ -7,11 +13,6 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; -import org.enso.interpreter.node.expression.builtin.meta.TypeOfNode; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.type.TypesGen; @GenerateUncached public abstract class TypeToDisplayTextNode extends Node { @@ -62,7 +63,7 @@ String doDisplay( return TypesGen.asUnresolvedSymbol(value).getName() + " (Unresolved_Symbol)"; } else if (TypesGen.isManagedResource(value)) { return "Managed_Resource"; - } else if (TypesGen.isArray(value)) { + } else if (objects.hasArrayElements(value)) { return "Array"; } else if (TypesGen.isRef(value)) { return "Ref"; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java index 4f4dbfe38da7..862d3f5ffa69 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java @@ -7,7 +7,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.library.ExportLibrary; @@ -32,9 +31,10 @@ import org.enso.interpreter.runtime.builtin.Builtins; import org.enso.interpreter.runtime.callable.CallerInfo; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.scope.LocalScope; import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.interpreter.runtime.type.Types; @@ -48,7 +48,7 @@ /** Represents a source module with a known location. */ @ExportLibrary(InteropLibrary.class) -public final class Module implements TruffleObject { +public final class Module implements EnsoObject { private ModuleScope scope; private ModuleSources sources; private PatchedModuleValues patchedValues; @@ -604,8 +604,8 @@ private static Object generateDocs(Module module, EnsoContext context) { @CompilerDirectives.TruffleBoundary private static Object gatherImportStatements(Module module, EnsoContext context) { - Object[] imports = context.getCompiler().gatherImportStatements(module); - return new Array(imports); + String[] imports = context.getCompiler().gatherImportStatements(module); + return ArrayLikeHelpers.wrapStrings(imports); } @CompilerDirectives.TruffleBoundary @@ -684,7 +684,7 @@ boolean isMemberInvocable(String member) { */ @ExportMessage Object getMembers(boolean includeInternal) { - return new Array( + return ArrayLikeHelpers.wrapStrings( MethodNames.Module.GET_METHOD, MethodNames.Module.REPARSE, MethodNames.Module.SET_SOURCE, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java index dd941c1ec739..0240c10fccf6 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java @@ -31,9 +31,9 @@ import org.enso.interpreter.runtime.callable.UnresolvedConversion; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.data.Array; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; /** Container for builtin Error types */ public final class Error { @@ -234,7 +234,8 @@ public Atom makeArityError(long expected_min, long expected_max, long actual) { * given method call */ public Atom makeUnsupportedArgumentsError(Object[] args, String message) { - return unsupportedArgumentsError.newInstance(new Array(args), message); + return unsupportedArgumentsError.newInstance( + ArrayLikeHelpers.wrapObjectsWithCheckAt(args), message); } /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedConversion.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedConversion.java index 66212c1dbe7d..0c3fd98b0053 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedConversion.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedConversion.java @@ -11,12 +11,13 @@ import org.enso.interpreter.node.callable.InteropConversionCallNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.scope.ModuleScope; /** Simple runtime value representing a yet-unresolved by-name symbol. */ @ExportLibrary(InteropLibrary.class) -public final class UnresolvedConversion implements TruffleObject { +public final class UnresolvedConversion implements EnsoObject { private final ModuleScope scope; /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedSymbol.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedSymbol.java index 9dfdecaec14f..68d5d85c9b44 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedSymbol.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/UnresolvedSymbol.java @@ -4,7 +4,8 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.interop.*; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -12,12 +13,13 @@ import org.enso.interpreter.node.callable.InteropMethodCallNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.scope.ModuleScope; /** Simple runtime value representing a yet-unresolved by-name symbol. */ @ExportLibrary(InteropLibrary.class) -public final class UnresolvedSymbol implements TruffleObject { +public final class UnresolvedSymbol implements EnsoObject { private final String name; private final ModuleScope scope; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java index 224da0db2509..e851976cddff 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java @@ -8,9 +8,10 @@ import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.error.PanicException; import org.enso.interpreter.runtime.error.WarningsLibrary; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; @@ -22,7 +23,6 @@ import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; @@ -37,7 +37,7 @@ */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -public abstract class Atom implements TruffleObject { +public abstract class Atom implements EnsoObject { final AtomConstructor constructor; private Integer hashCode; @@ -140,7 +140,7 @@ public boolean hasMembers() { @ExportMessage @CompilerDirectives.TruffleBoundary - public Array getMembers(boolean includeInternal) { + public EnsoObject getMembers(boolean includeInternal) { Map members = constructor.getDefinitionScope().getMethods().get(constructor.getType()); Set allMembers = new HashSet<>(); if (members != null) { @@ -150,8 +150,8 @@ public Array getMembers(boolean includeInternal) { if (members != null) { allMembers.addAll(members.keySet()); } - Object[] mems = allMembers.toArray(); - return new Array(mems); + String[] mems = allMembers.toArray(new String[0]); + return ArrayLikeHelpers.wrapStrings(mems); } @ExportMessage diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java index 6705b6e0cee1..897c047185d7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java @@ -6,7 +6,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -27,6 +26,7 @@ import org.enso.interpreter.runtime.callable.atom.unboxing.Layout; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.scope.LocalScope; @@ -36,7 +36,7 @@ /** A representation of an Atom constructor. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -public final class AtomConstructor implements TruffleObject { +public final class AtomConstructor implements EnsoObject { private final String name; private final ModuleScope definitionScope; @@ -51,12 +51,13 @@ public final class AtomConstructor implements TruffleObject { private final Type type; /** - * Creates a new Atom constructor for a given name. The constructor is not valid until {@link + * Creates a new Atom constructor for a given name.The constructor is not valid until {@link * AtomConstructor#initializeFields(EnsoLanguage, LocalScope, ExpressionNode[], ExpressionNode[], - * Annotation[], ArgumentDefinition...)} is called. + * Annotation[], ArgumentDefinition[])} is called. * * @param name the name of the Atom constructor * @param definitionScope the scope in which this constructor was defined + * @param type */ public AtomConstructor(String name, ModuleScope definitionScope, Type type) { this(name, definitionScope, type, false); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/unboxing/SuspendedFieldGetterNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/unboxing/SuspendedFieldGetterNode.java index 5760f8515892..566f3feddae8 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/unboxing/SuspendedFieldGetterNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/unboxing/SuspendedFieldGetterNode.java @@ -1,14 +1,15 @@ package org.enso.interpreter.runtime.callable.atom.unboxing; import com.oracle.truffle.api.exception.AbstractTruffleException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; + import org.enso.interpreter.node.callable.InvokeCallableNode; import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.state.State; /** @@ -55,7 +56,7 @@ public Object execute(Atom atom) { } } - private static final class SuspendedException implements TruffleObject { + private static final class SuspendedException implements EnsoObject { final AbstractTruffleException ex; SuspendedException(AbstractTruffleException ex) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java index 77619ca93247..0d889d47219e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java @@ -9,7 +9,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.library.CachedLibrary; @@ -24,8 +23,9 @@ import org.enso.interpreter.runtime.callable.Annotation; import org.enso.interpreter.runtime.callable.CallerInfo; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.state.State; import org.enso.interpreter.runtime.type.Types; @@ -34,7 +34,7 @@ /** A runtime representation of a function object in Enso. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -public final class Function implements TruffleObject { +public final class Function implements EnsoObject { private final RootCallTarget callTarget; private final MaterializedFrame scope; private final FunctionSchema schema; @@ -268,7 +268,7 @@ boolean hasMembers() { */ @ExportMessage Object getMembers(boolean includeInternal) { - return new Array(MethodNames.Function.EQUALS); + return ArrayLikeHelpers.wrapStrings(MethodNames.Function.EQUALS); } /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java index 9a47ba474feb..8bc82110a6ab 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -20,7 +19,7 @@ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "date", name = "Date", stdlibName = "Standard.Base.Data.Time.Date.Date") -public final class EnsoDate implements TruffleObject { +public final class EnsoDate implements EnsoObject { private final LocalDate date; public EnsoDate(LocalDate date) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java index 7568c8869c85..b5644bda019f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -25,7 +24,7 @@ pkg = "date", name = "DateTime", stdlibName = "Standard.Base.Data.Time.Date_Time.Date_Time") -public final class EnsoDateTime implements TruffleObject { +public final class EnsoDateTime implements EnsoObject { private final ZonedDateTime dateTime; public EnsoDateTime(ZonedDateTime dateTime) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java index 345744e5a9ce..774b8220e158 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -23,7 +22,7 @@ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "date", name = "Duration", stdlibName = "Standard.Base.Data.Time.Duration.Duration") -public final class EnsoDuration implements TruffleObject { +public final class EnsoDuration implements EnsoObject { private final Duration duration; public EnsoDuration(Duration duration) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java index a041bc8a964b..3fd7089cc4db 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java @@ -31,6 +31,8 @@ import java.time.ZonedDateTime; import java.util.Set; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; + import com.oracle.truffle.api.dsl.Cached; /** @@ -40,7 +42,7 @@ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "io", name = "File", stdlibName = "Standard.Base.System.File.File") -public final class EnsoFile implements TruffleObject { +public final class EnsoFile implements EnsoObject { private final TruffleFile truffleFile; public EnsoFile(TruffleFile truffleFile) { @@ -106,7 +108,7 @@ private static T[] convertInteropArray(Object arr, @Builtin.Method(name = "read_last_bytes_builtin") @Builtin.WrapException(from = IOException.class) @CompilerDirectives.TruffleBoundary - public ArrayOverBuffer readLastBytes(long n) throws IOException { + public EnsoObject readLastBytes(long n) throws IOException { try (SeekableByteChannel channel = this.truffleFile.newByteChannel(Set.of(StandardOpenOption.READ))) { int bytesToRead = Math.toIntExact(Math.min(channel.size(), n)); @@ -117,7 +119,7 @@ public ArrayOverBuffer readLastBytes(long n) throws IOException { } buffer.flip(); - return ArrayOverBuffer.wrapBuffer(buffer); + return ArrayLikeHelpers.wrapBuffer(buffer); } } @@ -213,8 +215,8 @@ public void createDirectories() { @Builtin.Method(name = "list_immediate_children_array") @Builtin.WrapException(from = IOException.class) @CompilerDirectives.TruffleBoundary - public EnsoFile[] list() throws IOException { - return this.truffleFile.list().stream().map(EnsoFile::new).toArray(EnsoFile[]::new); + public EnsoObject list() throws IOException { + return ArrayLikeHelpers.wrapEnsoObjects(this.truffleFile.list().stream().map(EnsoFile::new).toArray(EnsoFile[]::new)); } @Builtin.Method diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoObject.java new file mode 100644 index 000000000000..ce601581161b --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoObject.java @@ -0,0 +1,6 @@ +package org.enso.interpreter.runtime.data; + +import com.oracle.truffle.api.interop.TruffleObject; + +/** All non-primitive Enso types extends from {@code EnsoObject}. */ +public interface EnsoObject extends TruffleObject {} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java index 344b3f1a75ef..b0acbe5bf172 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java @@ -4,7 +4,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -24,7 +23,7 @@ pkg = "date", name = "TimeOfDay", stdlibName = "Standard.Base.Data.Time.Time_Of_Day.Time_Of_Day") -public final class EnsoTimeOfDay implements TruffleObject { +public final class EnsoTimeOfDay implements EnsoObject { private final LocalTime localTime; public EnsoTimeOfDay(LocalTime localTime) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java index 7186835cd431..b22fa65d42bf 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -22,7 +21,7 @@ pkg = "date", name = "TimeZone", stdlibName = "Standard.Base.Data.Time.Time_Zone.Time_Zone") -public final class EnsoTimeZone implements TruffleObject { +public final class EnsoTimeZone implements EnsoObject { private final ZoneId zone; public EnsoTimeZone(ZoneId zone) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java index d0fd4f644ce0..562976742f2f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java @@ -2,7 +2,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -16,7 +15,7 @@ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "resource", stdlibName = "Standard.Base.Runtime.Managed_Resource.Managed_Resource") -public final class ManagedResource implements TruffleObject { +public final class ManagedResource implements EnsoObject { private final Object resource; private final PhantomReference phantomReference; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java index a1bc65dc78ee..74f40cd64c65 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java @@ -2,7 +2,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -14,7 +13,7 @@ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "mutable", stdlibName = "Standard.Base.Runtime.Ref.Ref") -public final class Ref implements TruffleObject { +public final class Ref implements EnsoObject { private volatile Object value; /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java index 2cbc4b2759ef..58f889cff39b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; @@ -27,13 +26,14 @@ import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.pkg.QualifiedName; @ExportLibrary(TypesLibrary.class) @ExportLibrary(InteropLibrary.class) -public final class Type implements TruffleObject { +public final class Type implements EnsoObject { private final String name; private @CompilerDirectives.CompilationFinal ModuleScope definitionScope; private final boolean builtin; @@ -220,7 +220,7 @@ Object getMetaParents(@CachedLibrary("this") InteropLibrary lib) throw UnsupportedMessageException.create(); } assert getSupertype() != null; - return new Array(getSupertype()); + return ArrayLikeHelpers.wrapEnsoObjects(getSupertype()); } @ExportMessage @@ -286,8 +286,8 @@ boolean hasMembers() { @ExportMessage @CompilerDirectives.TruffleBoundary - Array getMembers(boolean includeInternal) { - return new Array(constructors.keySet().toArray(Object[]::new)); + EnsoObject getMembers(boolean includeInternal) { + return ArrayLikeHelpers.wrapStrings(constructors.keySet().toArray(String[]::new)); } @ExportMessage diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Vector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Vector.java deleted file mode 100644 index 5bf9ea7265f1..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Vector.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.enso.interpreter.runtime.data; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Cached.Shared; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; -import com.oracle.truffle.api.library.CachedLibrary; -import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; -import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; -import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.error.DataflowError; -import org.enso.interpreter.runtime.error.Warning; -import org.enso.interpreter.runtime.error.WarningsLibrary; -import org.enso.interpreter.runtime.error.WithWarnings; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; -import org.enso.interpreter.runtime.state.State; - -@ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) -@ExportLibrary(WarningsLibrary.class) -@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector") -public final class Vector implements TruffleObject { - private final Object storage; - - private Vector(Object storage) { - if (CompilerDirectives.inInterpreter()) { - if (!InteropLibrary.getUncached().hasArrayElements(storage)) { - throw new IllegalStateException("Vector needs array-like delegate, but got: " + storage); - } - } - this.storage = storage; - } - - @Builtin.Method( - name = "new", - description = "Creates new Vector with given length and provided elements.", - autoRegister = false) - @Builtin.Specialize() - public static Object newFromFunction( - VirtualFrame frame, - long length, - Function fun, - State state, - @Cached("buildWithArity(1)") InvokeFunctionNode invokeFunctionNode) { - Object[] target = new Object[Math.toIntExact(length)]; - for (int i = 0; i < target.length; i++) { - var value = invokeFunctionNode.execute(fun, frame, state, new Long[] {(long) i}); - if (value instanceof DataflowError) { - return value; - } - target[i] = value; - } - return new Vector(new Array(target)); - } - - @Builtin.Method( - name = "to_array", - description = "Returns an Array representation of this Vector.") - public final Object toArray() { - return this.storage; - } - - @Builtin.Method(description = "Returns the length of this Vector.") - @Builtin.Specialize - @Builtin.WrapException(from = UnsupportedMessageException.class) - public final long length(InteropLibrary interop) throws UnsupportedMessageException { - return interop.getArraySize(storage); - } - - // - // messages for the InteropLibrary - // - - /** - * Marks the object as array-like for Polyglot APIs. - * - * @return {@code true} - */ - @ExportMessage - boolean hasArrayElements() { - return true; - } - - @ExportMessage - long getArraySize(@Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) - throws UnsupportedMessageException { - return interop.getArraySize(storage); - } - - /** - * Handles reading an element by index through the polyglot API. - * - * @param index the index to read - * @return the element value at the provided index - * @throws InvalidArrayIndexException when the index is out of bounds. - */ - @ExportMessage - public Object readArrayElement( - long index, - @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop, - @CachedLibrary(limit = "3") WarningsLibrary warnings, - @Cached HostValueToEnsoNode toEnso) - throws InvalidArrayIndexException, UnsupportedMessageException { - var v = interop.readArrayElement(this.storage, index); - if (warnings.hasWarnings(this.storage)) { - Warning[] extracted = warnings.getWarnings(this.storage, null); - if (warnings.hasWarnings(v)) { - v = warnings.removeWarnings(v); - } - return WithWarnings.wrap(EnsoContext.get(interop), toEnso.execute(v), extracted); - } - return toEnso.execute(v); - } - - public static Vector fromArray(Object arr) { - return new Vector(arr); - } - - /** - * Exposes an index validity check through the polyglot API. - * - * @param index the index to check - * @return {@code true} if the index is valid, {@code false} otherwise. - */ - @ExportMessage - boolean isArrayElementReadable( - long index, @Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) { - try { - var size = interop.getArraySize(storage); - return index < size && index >= 0; - } catch (UnsupportedMessageException e) { - return false; - } - } - - @ExportMessage - boolean isArrayElementModifiable(long index) { - return false; - } - - @ExportMessage - final void writeArrayElement(long index, Object value) - throws UnsupportedMessageException, UnsupportedTypeException, InvalidArrayIndexException { - throw UnsupportedMessageException.create(); - } - - @ExportMessage - boolean isArrayElementInsertable(long index) { - return false; - } - - @ExportMessage - boolean isArrayElementRemovable(long index) { - return false; - } - - @ExportMessage - final void removeArrayElement(long index) throws UnsupportedMessageException { - throw UnsupportedMessageException.create(); - } - - @ExportMessage - @CompilerDirectives.TruffleBoundary - String toDisplayString(boolean allowSideEffects) { - final InteropLibrary iop = InteropLibrary.getUncached(); - return DisplayArrayUtils.toDisplayString(this, allowSideEffects, iop); - } - - @ExportMessage - Type getMetaObject(@CachedLibrary("this") InteropLibrary thisLib) { - return EnsoContext.get(thisLib).getBuiltins().vector(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - // - // methods for TypesLibrary - // - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@CachedLibrary("this") TypesLibrary thisLib, @Cached("1") int ignore) { - return EnsoContext.get(thisLib).getBuiltins().vector(); - } - - @ExportMessage - boolean hasWarnings(@Shared("warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) { - return warnings.hasWarnings(this.storage); - } - - @ExportMessage - Warning[] getWarnings( - Node location, @Shared("warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) - throws UnsupportedMessageException { - return warnings.getWarnings(this.storage, location); - } - - @ExportMessage - Vector removeWarnings(@Shared("warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) - throws UnsupportedMessageException { - return new Vector(warnings.removeWarnings(this.storage)); - } - - @ExportMessage - boolean isLimitReached(@Shared("warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) { - return warnings.isLimitReached(this.storage); - } - - // - // helper methods - // - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - return toDisplayString(false); - } - - @SuppressWarnings("unchecked") - private static E raise(Class clazz, Throwable t) throws E { - throw (E) t; - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java index fc95c9e5e29f..e9bd98868264 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownKeyException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; @@ -14,9 +13,10 @@ import org.enso.interpreter.node.expression.builtin.meta.EqualsNode; import org.enso.interpreter.node.expression.builtin.meta.HashCodeNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.data.Vector; import org.enso.interpreter.runtime.data.hash.EnsoHashMapBuilder.StorageEntry; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** @@ -32,7 +32,7 @@ @ExportLibrary(TypesLibrary.class) @ExportLibrary(InteropLibrary.class) @Builtin(stdlibName = "Standard.Base.Data.Map.Map", name = "Map") -public final class EnsoHashMap implements TruffleObject { +public final class EnsoHashMap implements EnsoObject { private final EnsoHashMapBuilder mapBuilder; /** * Size of this Map. Basically an index into {@link EnsoHashMapBuilder}'s storage. See {@link @@ -83,7 +83,8 @@ Object getCachedVectorRepresentation(ConditionProfile isNotCachedProfile) { } } cachedVectorRepresentation = - Vector.fromArray(HashEntriesVector.createFromKeysAndValues(keys, values)); + ArrayLikeHelpers.asVectorFromArray( + HashEntriesVector.createFromKeysAndValues(keys, values)); } return cachedVectorRepresentation; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashEntriesVector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashEntriesVector.java index 7060794ad0fd..3977dbcb8d70 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashEntriesVector.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashEntriesVector.java @@ -3,11 +3,11 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import org.enso.interpreter.runtime.data.Vector; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; /** * A vector used to hold hash map entries, where each entry is represented as a 2-element vector. @@ -15,14 +15,14 @@ * (array), and for Enso {@code Map.to_vector} method. May be empty. */ @ExportLibrary(InteropLibrary.class) -final class HashEntriesVector implements TruffleObject { - private final Vector[] entryPairs; +final class HashEntriesVector implements EnsoObject { + private final EnsoObject[] entryPairs; private HashEntriesVector(Object[] keys, Object[] values) { assert keys.length == values.length; - this.entryPairs = new Vector[keys.length]; + this.entryPairs = new EnsoObject[keys.length]; for (int i = 0; i < keys.length; i++) { - entryPairs[i] = Vector.fromArray(new EntryPair(keys[i], values[i])); + entryPairs[i] = ArrayLikeHelpers.asVectorFromArray(new EntryPair(keys[i], values[i])); } } @@ -74,7 +74,7 @@ void writeArrayElement(long index, Object value) throws UnsupportedMessageExcept } @ExportLibrary(InteropLibrary.class) - static final class EntryPair implements TruffleObject { + static final class EntryPair implements EnsoObject { private final Object key; private final Object value; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashMapToVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashMapToVectorNode.java index 008e41062088..af3d9b875c8a 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashMapToVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/HashMapToVectorNode.java @@ -1,5 +1,8 @@ package org.enso.interpreter.runtime.data.hash; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; + import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateUncached; @@ -11,9 +14,6 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.data.Vector; - @BuiltinMethod( type = "Map", @@ -48,7 +48,7 @@ Object foreignMapToVector(Object hashMap, @Fallback Object fallback(Object object) { - return Vector.fromArray(HashEntriesVector.createEmpty()); + return ArrayLikeHelpers.asVectorWithCheckAt(HashEntriesVector.createEmpty()); } private static Object createEntriesVectorFromForeignMap( @@ -67,7 +67,7 @@ private static Object createEntriesVectorFromForeignMap( values[arrIdx] = iteratorInterop.readArrayElement(keyValueArr, 1); arrIdx++; } - return Vector.fromArray( + return ArrayLikeHelpers.asVectorFromArray( HashEntriesVector.createFromKeysAndValues(keys, values) ); } catch (UnsupportedMessageException | StopIterationException | InvalidArrayIndexException e) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java index a54645c52ff3..6509a7d61a32 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java @@ -8,6 +8,7 @@ import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Text_Utils; @@ -16,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -24,7 +24,7 @@ /** The main runtime type for Enso's Text. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -public final class Text implements TruffleObject { +public final class Text implements EnsoObject { private static final Lock LOCK = new ReentrantLock(); private volatile Object contents; private volatile int length = -1; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java similarity index 83% rename from engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java index 3939bd273c19..0867c544c215 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java @@ -1,11 +1,10 @@ -package org.enso.interpreter.runtime.data; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -15,6 +14,8 @@ import java.util.Arrays; import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.error.Warning; import org.enso.interpreter.runtime.error.WarningsLibrary; import org.enso.interpreter.runtime.error.WithWarnings; @@ -26,7 +27,7 @@ @ExportLibrary(TypesLibrary.class) @ExportLibrary(WarningsLibrary.class) @Builtin(pkg = "mutable", stdlibName = "Standard.Base.Data.Array.Array") -public final class Array implements TruffleObject { +final class Array implements EnsoObject { private final Object[] items; private Boolean withWarnings; private Warning[] cachedWarnings; @@ -36,22 +37,11 @@ public final class Array implements TruffleObject { * * @param items the element values */ - public Array(Object... items) { + Array(Object... items) { assert noNulls(items); this.items = items; } - /** - * Creates an uninitialized array of the given size. The values must be filled before the array is - * returned to Enso. - * - * @param size the size of the created array. - */ - public static Array allocate(long size) { - var arr = new Object[(int) size]; - return new Array(arr); - } - private static boolean noNulls(Object[] arr) { for (Object o : arr) { if (o == null) { @@ -62,7 +52,7 @@ private static boolean noNulls(Object[] arr) { } /** @return the elements of this array as a java array. */ - public Object[] getItems() { + final Object[] getItems() { return items; } @@ -72,7 +62,7 @@ public Object[] getItems() { * @return {@code true} */ @ExportMessage - public boolean hasArrayElements() { + boolean hasArrayElements() { return true; } @@ -84,7 +74,7 @@ public boolean hasArrayElements() { * @throws InvalidArrayIndexException when the index is out of bounds. */ @ExportMessage - public Object readArrayElement( + Object readArrayElement( long index, @CachedLibrary(limit = "3") WarningsLibrary warnings, @Cached BranchProfile errProfile, @@ -108,29 +98,10 @@ public Object readArrayElement( return v; } - public long length() { + long length() { return items.length; } - /** @return an empty array */ - public static Array empty() { - return allocate(0); - } - - /** - * Takes a slice from an array like object. - * - * @param self array like object - * @param start start of the slice - * @param end end of the slice - * @param len the length of the array - * @return an array-like object representing the slice - */ - public static Object slice(Object self, long start, long end, long len) { - var slice = ArraySlice.createOrNull(self, start, len, end); - return slice == null ? self : slice; - } - /** * Exposes the size of this collection through the polyglot API. * diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayBuilder.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayBuilder.java new file mode 100644 index 000000000000..e801896d0e8c --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayBuilder.java @@ -0,0 +1,220 @@ +package org.enso.interpreter.runtime.data.vector; + +import java.util.Arrays; + +import org.enso.interpreter.runtime.data.EnsoObject; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.InvalidArrayIndexException; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.Node; + +@ExportLibrary(InteropLibrary.class) +final class ArrayBuilder implements EnsoObject { + private static final String[] MEMBERS = new String[] { "isEmpty", "add", "appendTo", "get", "getSize", "toArray" }; + private static final Object[] EMPTY_ARRAY = new Object[0]; + private final int initialCapacity; + private int size; + private Object primitiveArray; + private Object[] objectArray; + + private ArrayBuilder(int initialCapacity) { + this.initialCapacity = Math.max(1, initialCapacity); + } + + /** + * Creates new builder + */ + static ArrayBuilder newBuilder(int capacity) { + return new ArrayBuilder(capacity); + } + + /** + * Is the builder empty? + */ + boolean isEmpty() { + return size == 0; + } + + /** + * Adds an element to the builder + * + * @param e the element to add + */ + void add(Object e) { + if (objectArray != null) { + if (size == objectArray.length) { + CompilerDirectives.transferToInterpreter(); + objectArray = Arrays.copyOf(objectArray, size * 2); + } + objectArray[size++] = e; + } else if (primitiveArray instanceof long[] longArray) { + if (e instanceof Long l) { + if (size == longArray.length) { + CompilerDirectives.transferToInterpreter(); + primitiveArray = longArray = Arrays.copyOf(longArray, size * 2); + } + longArray[size++] = l; + } else { + CompilerDirectives.transferToInterpreter(); + objectArray = new Object[longArray.length]; + for (int i = 0; i < size; i++) { + objectArray[i] = longArray[i]; + } + primitiveArray = null; + add(e); + } + } else if (primitiveArray instanceof double[] doubleArray) { + if (e instanceof Double d) { + if (size == doubleArray.length) { + CompilerDirectives.transferToInterpreter(); + primitiveArray = doubleArray = Arrays.copyOf(doubleArray, size * 2); + } + doubleArray[size++] = d; + } else { + CompilerDirectives.transferToInterpreter(); + objectArray = new Object[doubleArray.length]; + for (int i = 0; i < size; i++) { + objectArray[i] = doubleArray[i]; + } + primitiveArray = null; + add(e); + } + } else { + assert objectArray == null; + assert primitiveArray == null; + assert size == 0; + if (e instanceof Long l) { + var arr = new long[initialCapacity]; + arr[0] = l; + primitiveArray = arr; + } else if (e instanceof Double d) { + var arr = new double[initialCapacity]; + arr[0] = d; + primitiveArray = arr; + } else { + var arr = new Object[initialCapacity]; + arr[0] = e; + objectArray = arr; + } + size = 1; + } + } + + /** + * Obtains an element from the builder + */ + private Object get(int index, Node node) { + try { + if (index >= 0 && index < size) { + if (objectArray != null) { + return objectArray[index]; + } else if (primitiveArray instanceof long[] longArray) { + return longArray[index]; + } else if (primitiveArray instanceof double[] doubleArray) { + return doubleArray[index]; + } + } + throw new ArrayIndexOutOfBoundsException(); + } catch (IndexOutOfBoundsException e) { + throw ArrayPanics.indexOutOfBounds(node, index, size); + } + } + + /** + * Returns the current array of the builder. + */ + Object toArray() { + if (objectArray != null) { + return objectArray.length == size ? objectArray : Arrays.copyOf(objectArray, size); + } else if (primitiveArray instanceof long[] longArray) { + return longArray.length == size ? longArray : Arrays.copyOf(longArray, size); + } else if (primitiveArray instanceof double[] doubleArray) { + return doubleArray.length == size ? doubleArray : Arrays.copyOf(doubleArray, size); + } else { + return EMPTY_ARRAY; + } + } + + int getSize() { + return size; + } + + @ExportMessage + Object invokeMember( + String name, Object[] args, + @CachedLibrary(limit="3") InteropLibrary iop + ) throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException { + return switch (name) { + case "isEmpty" -> isEmpty(); + case "add" -> { + add(args[0]); + yield this; + } + case "appendTo" -> { + long len = iop.getArraySize(args[0]); + for (var i = 0; i < len; i++) { + try { + var e = iop.readArrayElement(args[0], i); + add(e); + } catch (InvalidArrayIndexException ex) { + throw UnsupportedTypeException.create(args); + } + } + yield this; + } + case "get" -> { + if (!iop.isNumber(args[0])) { + throw UnsupportedTypeException.create(args); + } + if (!iop.fitsInInt(args[0])) { + throw UnsupportedTypeException.create(args); + } + var index = iop.asInt(args[0]); + yield get(index, iop); + } + case "getSize" -> getSize(); + case "toArray" -> { + var arr = toArray(); + if (arr instanceof long[] longs) { + yield Vector.fromLongArray(longs); + } + if (arr instanceof double[] doubles) { + yield Vector.fromDoubleArray(doubles); + } + yield Vector.fromInteropArray(new Array((Object[])arr)); + } + default -> throw UnknownIdentifierException.create(name); + }; + } + + @ExportMessage + boolean hasMembers() { + return true; + } + @ExportMessage + boolean isMemberInvocable(String member) { + for (var m : MEMBERS) { + if (m.equals(member)) { + return true; + } + } + return false; + } + + @ExportMessage + EnsoObject getMembers(boolean includeInternal) { + return ArrayLikeHelpers.wrapStrings(MEMBERS); + } + + @ExportMessage + String toDisplayString(boolean ignore) { + return "Array_Builder"; + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeAtNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeAtNode.java new file mode 100644 index 000000000000..24977e4db071 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeAtNode.java @@ -0,0 +1,74 @@ +package org.enso.interpreter.runtime.data.vector; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.NeverDefault; +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.Node; +import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; +import org.enso.interpreter.runtime.error.WarningsLibrary; + +public abstract class ArrayLikeAtNode extends Node { + public abstract Object executeAt(Object arrayLike, long index) throws InvalidArrayIndexException; + + @NeverDefault + public static ArrayLikeAtNode create() { + return ArrayLikeAtNodeGen.create(); + } + + // + // implementation + // + + @Specialization + Object arrayAt(Array self, long index) throws InvalidArrayIndexException { + try { + return self.getItems()[Math.toIntExact(index)]; + } catch (ArithmeticException | IndexOutOfBoundsException ex) { + throw InvalidArrayIndexException.create(index, ex); + } + } + + @Specialization + Object vectorLongAt(Vector.Long self, long index) throws InvalidArrayIndexException { + return self.readArrayElement(index); + } + + @Specialization + Object vectorDoubleAt(Vector.Double self, long index) throws InvalidArrayIndexException { + return self.readArrayElement(index); + } + + @Specialization + Object vectorAt( + Vector.Generic self, + long index, + @Cached.Exclusive @CachedLibrary(limit = "3") InteropLibrary interop, + @Cached.Exclusive @CachedLibrary(limit = "3") WarningsLibrary warnings, + @Cached.Exclusive @Cached HostValueToEnsoNode convert) + throws InvalidArrayIndexException { + try { + return self.readArrayElement(index, interop, warnings, convert); + } catch (UnsupportedMessageException ex) { + throw ArrayPanics.notAnArrayPanic(this, self); + } + } + + @Specialization + Object genericAt( + Object self, + long index, + @Cached.Exclusive @CachedLibrary(limit = "3") InteropLibrary interop, + @Cached.Exclusive @Cached HostValueToEnsoNode convert) + throws InvalidArrayIndexException { + try { + var element = interop.readArrayElement(self, index); + return convert.execute(element); + } catch (UnsupportedMessageException ex) { + throw ArrayPanics.notAnArrayPanic(this, self); + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CoerceArrayNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCoerceToArrayNode.java similarity index 60% rename from engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CoerceArrayNode.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCoerceToArrayNode.java index 658ebaf7fdf8..37cc3d52a1e0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CoerceArrayNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCoerceToArrayNode.java @@ -1,4 +1,4 @@ -package org.enso.interpreter.node.expression.builtin.mutable; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -10,19 +10,13 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.Vector; -import org.enso.interpreter.runtime.error.PanicException; -public abstract class CoerceArrayNode extends Node { +public abstract class ArrayLikeCoerceToArrayNode extends Node { private @Child InteropLibrary library = InteropLibrary.getFactory().createDispatched(10); @NeverDefault - public static CoerceArrayNode build() { - return CoerceArrayNodeGen.create(); + public static ArrayLikeCoerceToArrayNode build() { + return ArrayLikeCoerceToArrayNodeGen.create(); } public abstract Object[] execute(Object value); @@ -33,7 +27,7 @@ Object[] doArray(Array arr) { } @Specialization - Object[] doVector(Vector arr, @Cached CoerceArrayNode coerceArrayNode) { + Object[] doVector(Vector.Generic arr, @Cached ArrayLikeCoerceToArrayNode coerceArrayNode) { return coerceArrayNode.execute(arr.toArray()); } @@ -45,13 +39,9 @@ Object[] doArrayLike( try { return convertToArray(arr, hostValueToEnsoNode); } catch (UnsupportedMessageException e) { - Builtins builtins = EnsoContext.get(this).getBuiltins(); - Atom err = builtins.error().makeTypeError(builtins.array(), arr, "arr"); - throw new PanicException(err, this); + throw ArrayPanics.typeError(this, arr, "arr"); } catch (InvalidArrayIndexException e) { - Builtins builtins = EnsoContext.get(this).getBuiltins(); - throw new PanicException( - builtins.error().makeInvalidArrayIndex(arr, e.getInvalidIndex()), this); + throw ArrayPanics.invalidIndex(this, arr, e); } } @@ -67,8 +57,6 @@ private Object[] convertToArray(Object arr, HostValueToEnsoNode hostValueToEnsoN @Fallback Object[] doOther(Object arr) { - Builtins builtins = EnsoContext.get(this).getBuiltins(); - Atom error = builtins.error().makeTypeError("array", arr, "arr"); - throw new PanicException(error, this); + throw ArrayPanics.typeError(this, arr, "arr"); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CopyNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCopyToArrayNode.java similarity index 65% rename from engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CopyNode.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCopyToArrayNode.java index 803fa57a6122..46413d4f5e6b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CopyNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeCopyToArrayNode.java @@ -1,4 +1,4 @@ -package org.enso.interpreter.node.expression.builtin.mutable; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -10,17 +10,15 @@ import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.EnsoObject; -public abstract class CopyNode extends Node { - public static CopyNode build() { - return CopyNodeGen.create(); +public abstract class ArrayLikeCopyToArrayNode extends Node { + public static ArrayLikeCopyToArrayNode build() { + return ArrayLikeCopyToArrayNodeGen.create(); } public abstract Object execute( - Object src, long source_index, Array dest, long dest_index, long count); + Object src, long srcIndex, EnsoObject destArr, long destIndex, long count); @Specialization Object doArray(Array src, long source_index, Array dest, long dest_index, long count) { @@ -46,19 +44,13 @@ Object doPolyglotArray( } catch (UnsupportedMessageException e) { throw new IllegalStateException("Unreachable"); } catch (InvalidArrayIndexException e) { - throw new PanicException( - EnsoContext.get(this) - .getBuiltins() - .error() - .makeInvalidArrayIndex(src, e.getInvalidIndex()), - this); + throw ArrayPanics.invalidIndex(this, src, e); } return EnsoContext.get(this).getBuiltins().nothing(); } @Fallback - Object doOther(Object src, long source_index, Array dest, long dest_index, long count) { - Builtins builtins = EnsoContext.get(this).getBuiltins(); - throw new PanicException(builtins.error().makeTypeError(builtins.array(), src, "src"), this); + Object doOther(Object src, long source_index, EnsoObject dest, long dest_index, long count) { + throw ArrayPanics.typeError(this, src, "src"); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java new file mode 100644 index 000000000000..c89405cf6e8d --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java @@ -0,0 +1,161 @@ +package org.enso.interpreter.runtime.data.vector; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.frame.VirtualFrame; + +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; + +import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.error.DataflowError; +import org.enso.interpreter.runtime.error.WarningsLibrary; +import org.enso.interpreter.runtime.state.State; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.library.CachedLibrary; + +/** Publicly available operations on array-like classes. */ +@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Internal.Array_Like_Helpers") +public final class ArrayLikeHelpers { + private ArrayLikeHelpers() {} + + @Builtin.Method( + name = "new_array_proxy_builtin", + description = "Creates an array backed by a proxy object.") + @Builtin.WrapException(from = IllegalArgumentException.class) + public static EnsoObject create(long length, Object at) throws IllegalArgumentException { + return ArrayProxy.create(length, at); + } + + /** Checks whether an array like object is considered immutable. + * Immutable objects are instances of {@link EnsoObject} and can be safely cast + * to that interface. + * + * @param obj the object to check + * @return if the {@code obj} is already seen as immutable + */ + public static boolean isImmutable(Object obj) { + return obj instanceof Vector; + } + + /** + * Takes a slice from an array like object. + * + * @param self array like object + * @param start start of the slice + * @param end end of the slice + * @param len the length of the array + * @return an array-like object representing the slice + */ + public static Object slice(Object self, long start, long end, long len) { + var slice = ArraySlice.createOrNull(self, start, len, end); + return slice == null ? self : slice; + } + + /** + * Creates an uninitialized array of the given size.The values must be filled before the array is + * returned to Enso. + * + * @param size the size of the created array. + * @return the array instance + */ + public static EnsoObject allocate(long size) { + var arr = new Object[Math.toIntExact(size)]; + return new Array(arr); + } + + @Builtin.Method( + name = "vector_from_function", + description = "Creates new Vector with given length and provided elements.", + autoRegister = false) + @Builtin.Specialize() + public static Object vectorFromFunction( + VirtualFrame frame, + long length, + Function fun, + State state, + @Cached("buildWithArity(1)") InvokeFunctionNode invokeFunctionNode, + @CachedLibrary(limit="3") WarningsLibrary warnings + ) { + var len = Math.toIntExact(length); + var target = ArrayBuilder.newBuilder(len); + boolean nonTrivialEnsoValue = false; + for (int i = 0; i < len; i++) { + var value = invokeFunctionNode.execute(fun, frame, state, new Long[] {(long) i}); + if (value instanceof DataflowError) { + return value; + } + if (warnings.hasWarnings(value)) { + nonTrivialEnsoValue = true; + } else { + var isEnsoValue = value instanceof EnsoObject || value instanceof Long || value instanceof Double; + if (!isEnsoValue) { + nonTrivialEnsoValue = true; + } + } + target.add(value); + } + var res = target.toArray(); + if (res instanceof long[] longs) { + return Vector.fromLongArray(longs); + } + if (res instanceof double[] doubles) { + return Vector.fromDoubleArray(doubles); + } + if (nonTrivialEnsoValue) { + return Vector.fromInteropArray(new Array((Object[])res)); + } else { + return Vector.fromEnsoOnlyArray((Object[])res); + } + } + + @Builtin.Method( + name = "vector_to_array", + description = "Returns an Array representation of this Vector.") + public static Object vectorToArray(Object obj) { + if (obj instanceof Vector.Generic vector) { + return vector.toArray(); + } else { + return obj; + } + } + + @Builtin.Method( + name = "new_vector_builder", + description = "Returns new vector builder.") + public static Object newVectorBuilder(long capacity) { + return ArrayBuilder.newBuilder((int)Math.min(Math.abs(capacity),Integer.MAX_VALUE)); + } + + public static EnsoObject wrapBuffer(ByteBuffer buffer) { + return ArrayOverBuffer.wrapBuffer(buffer); + } + + public static EnsoObject wrapEnsoObjects(EnsoObject... arr) { + return new Array((Object[]) arr); + } + + public static EnsoObject wrapStrings(String... arr) { + return new Array((Object[]) arr); + } + + public static EnsoObject wrapObjectsWithCheckAt(Object... arr) { + return new Array((Object[]) arr); + } + + public static EnsoObject empty() { + return allocate(0); + } + + public static EnsoObject asVectorWithCheckAt(Object... arr) { + return Vector.fromInteropArray(new Array((Object[]) arr)); + } + + public static EnsoObject asVectorFromArray(Object storage) { + return Vector.fromInteropArray(storage); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeLengthNode.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeLengthNode.java new file mode 100644 index 000000000000..e7b219dfefeb --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeLengthNode.java @@ -0,0 +1,57 @@ +package org.enso.interpreter.runtime.data.vector; + +import com.oracle.truffle.api.dsl.Cached.Exclusive; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.NeverDefault; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.nodes.Node; + +public abstract class ArrayLikeLengthNode extends Node { + public abstract long executeLength(Object arrayLike); + + @NeverDefault + public static ArrayLikeLengthNode create() { + return ArrayLikeLengthNodeGen.create(); + } + + // + // implementation + // + + @Specialization + static long arrayLength(Array self) { + return self.length(); + } + + @Specialization + static long vectorLongLength(Vector.Long self) { + return self.getArraySize(); + } + + @Specialization + static long vectorDoubleLength(Vector.Double self) { + return self.getArraySize(); + } + + @Specialization + long vectorLength( + Vector.Generic self, @Exclusive @CachedLibrary(limit = "3") InteropLibrary iop) { + try { + return self.getArraySize(iop); + } catch (UnsupportedMessageException ex) { + throw ArrayPanics.notAnArrayPanic(this, self); + } + } + + @Fallback + long foreignLength(Object self, @Exclusive @CachedLibrary(limit = "3") InteropLibrary iop) { + try { + return iop.getArraySize(self); + } catch (UnsupportedMessageException ex) { + throw ArrayPanics.notAnArrayPanic(this, self); + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayOverBuffer.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayOverBuffer.java similarity index 84% rename from engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayOverBuffer.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayOverBuffer.java index f7f2a4caef53..c2482ada367f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayOverBuffer.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayOverBuffer.java @@ -1,14 +1,14 @@ -package org.enso.interpreter.runtime.data; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import java.nio.ByteBuffer; +import org.enso.interpreter.runtime.data.EnsoObject; @ExportLibrary(InteropLibrary.class) -public final class ArrayOverBuffer implements TruffleObject { +final class ArrayOverBuffer implements EnsoObject { private final ByteBuffer buffer; private ArrayOverBuffer(ByteBuffer buffer) { @@ -39,7 +39,7 @@ long getArraySize() { return buffer.remaining(); } - public static ArrayOverBuffer wrapBuffer(ByteBuffer buffer) { + static ArrayOverBuffer wrapBuffer(ByteBuffer buffer) { return new ArrayOverBuffer(buffer); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayPanics.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayPanics.java new file mode 100644 index 000000000000..4f7467c8d7e6 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayPanics.java @@ -0,0 +1,43 @@ +package org.enso.interpreter.runtime.data.vector; + +import com.oracle.truffle.api.interop.InvalidArrayIndexException; +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.error.PanicException; + +final class ArrayPanics { + private ArrayPanics() {} + + static PanicException notAnArrayPanic(Node node, Object self) { + var ctx = EnsoContext.get(node); + var err = + ctx.getBuiltins() + .error() + .makeUnsupportedArgumentsError(new Object[] {self}, "Not an array"); + return new PanicException(err, node); + } + + static PanicException unsupportedArgument(Node node, Object arg, String msg) { + var ctx = EnsoContext.get(node); + var err = ctx.getBuiltins().error().makeUnsupportedArgumentsError(new Object[] {arg}, msg); + return new PanicException(err, node); + } + + static PanicException indexOutOfBounds(Node node, int index, int size) { + var ctx = EnsoContext.get(node); + var err = ctx.getBuiltins().error().makeIndexOutOfBounds(index, size); + throw new PanicException(err, node); + } + + static PanicException invalidIndex(Node node, Object src, InvalidArrayIndexException e) { + var ctx = EnsoContext.get(node); + var err = ctx.getBuiltins().error().makeInvalidArrayIndex(src, e.getInvalidIndex()); + return new PanicException(err, node); + } + + static PanicException typeError(Node node, Object src, String msg) { + var builtins = EnsoContext.get(node).getBuiltins(); + var err = builtins.error().makeTypeError(builtins.array(), src, msg); + return new PanicException(err, node); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayProxy.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java similarity index 81% rename from engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayProxy.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java index 513d9a8373bf..34f41693236a 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArrayProxy.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java @@ -1,4 +1,4 @@ -package org.enso.interpreter.runtime.data; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; @@ -6,16 +6,15 @@ import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** @@ -26,9 +25,8 @@ */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Array_Proxy.Array_Proxy") @ImportStatic(BranchProfile.class) -public final class ArrayProxy implements TruffleObject { +final class ArrayProxy implements EnsoObject { private final long length; private final Object at; @@ -36,9 +34,8 @@ private ArrayProxy(long length, Object at) throws IllegalArgumentException { if (CompilerDirectives.inInterpreter()) { InteropLibrary interop = InteropLibrary.getUncached(); if (!interop.isExecutable(at)) { - throw new PanicException( - EnsoContext.get(interop).getBuiltins().error().makeTypeError("Function", at, "at"), - interop); + var msg = "Array_Proxy needs executable function."; + throw ArrayPanics.typeError(interop, at, msg); } } @@ -51,9 +48,7 @@ private ArrayProxy(long length, Object at) throws IllegalArgumentException { this.at = at; } - @Builtin.Method(name = "new_builtin", description = "Creates an array backed by a proxy object.") - @Builtin.WrapException(from = IllegalArgumentException.class) - public static ArrayProxy create(long length, Object at) throws IllegalArgumentException { + static ArrayProxy create(long length, Object at) throws IllegalArgumentException { return new ArrayProxy(length, at); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArraySlice.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArraySlice.java similarity index 95% rename from engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArraySlice.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArraySlice.java index f1b6149606ba..28a05db8e2e0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ArraySlice.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArraySlice.java @@ -1,25 +1,26 @@ -package org.enso.interpreter.runtime.data; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; 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.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; + import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.error.Warning; import org.enso.interpreter.runtime.error.WarningsLibrary; import org.enso.interpreter.runtime.error.WithWarnings; @ExportLibrary(InteropLibrary.class) @ExportLibrary(WarningsLibrary.class) -public final class ArraySlice implements TruffleObject { +final class ArraySlice implements EnsoObject { private final Object storage; private final long start; private final long end; @@ -47,13 +48,13 @@ static Vector createOrNull(Object storage, long start, long this_length, long en long slice_end = Math.min(this_length, end); Object slice; if (slice_start >= slice_end) { - slice = Array.allocate(0); + slice = ArrayLikeHelpers.allocate(0); } else if ((slice_start == 0) && (slice_end == this_length)) { return null; } else { slice = new ArraySlice(storage, slice_start, slice_end); } - return Vector.fromArray(slice); + return Vector.fromInteropArray(slice); } /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/DisplayArrayUtils.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/DisplayArrayUtils.java similarity index 93% rename from engine/runtime/src/main/java/org/enso/interpreter/runtime/data/DisplayArrayUtils.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/DisplayArrayUtils.java index 6bba4818a0ec..050cbc93b078 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/DisplayArrayUtils.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/DisplayArrayUtils.java @@ -1,4 +1,4 @@ -package org.enso.interpreter.runtime.data; +package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.InteropLibrary; @@ -7,7 +7,8 @@ import java.io.PrintWriter; import java.io.StringWriter; -public class DisplayArrayUtils { +final class DisplayArrayUtils { + private DisplayArrayUtils() {} @CompilerDirectives.TruffleBoundary public static String toDisplayString( diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java new file mode 100644 index 000000000000..4344f7778950 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java @@ -0,0 +1,395 @@ +package org.enso.interpreter.runtime.data.vector; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +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.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.error.Warning; +import org.enso.interpreter.runtime.error.WarningsLibrary; +import org.enso.interpreter.runtime.error.WithWarnings; +import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; + +@ExportLibrary(InteropLibrary.class) +@ExportLibrary(TypesLibrary.class) +@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector") +abstract class Vector implements EnsoObject { + @ExportMessage + boolean hasArrayElements() { + return true; + } + + @ExportMessage + boolean isArrayElementModifiable(long index) { + return false; + } + + @ExportMessage + boolean isArrayElementReadable(long index) { + return true; + } + + @ExportMessage + long getArraySize() { + throw CompilerDirectives.shouldNotReachHere(); + } + + @ExportMessage + Object readArrayElement(long index) + throws UnsupportedMessageException, InvalidArrayIndexException { + throw CompilerDirectives.shouldNotReachHere(); + } + + @ExportMessage + final void writeArrayElement(long index, Object value) throws UnsupportedMessageException { + throw UnsupportedMessageException.create(); + } + + @ExportMessage + boolean isArrayElementInsertable(long index) { + return false; + } + + @ExportMessage + boolean isArrayElementRemovable(long index) { + return false; + } + + @ExportMessage + final void removeArrayElement(long index) throws UnsupportedMessageException { + throw UnsupportedMessageException.create(); + } + + @ExportMessage + @CompilerDirectives.TruffleBoundary + String toDisplayString(boolean allowSideEffects) { + final InteropLibrary iop = InteropLibrary.getUncached(); + return DisplayArrayUtils.toDisplayString(this, allowSideEffects, iop); + } + + @ExportMessage + Type getMetaObject(@CachedLibrary("this") InteropLibrary thisLib) { + return EnsoContext.get(thisLib).getBuiltins().vector(); + } + + @ExportMessage + boolean hasMetaObject() { + return true; + } + + // + // methods for TypesLibrary + // + + @ExportMessage + boolean hasType() { + return true; + } + + @ExportMessage + Type getType(@CachedLibrary("this") TypesLibrary thisLib, @Cached("1") int ignore) { + return EnsoContext.get(thisLib).getBuiltins().vector(); + } + + // + // helper methods + // + + @Override + @CompilerDirectives.TruffleBoundary + public String toString() { + return toDisplayString(false); + } + + static Vector fromInteropArray(Object arr) { + return new Generic(arr); + } + + static Vector fromLongArray(long[] arr) { + return new Long(arr); + } + + static Vector fromDoubleArray(double[] arr) { + return new Double(arr); + } + + static Object fromEnsoOnlyArray(Object[] arr) { + return new EnsoOnly(arr); + } + + @ExportLibrary(InteropLibrary.class) + @ExportLibrary(WarningsLibrary.class) + static final class EnsoOnly extends Vector { + private final Object[] storage; + + private EnsoOnly(Object[] storage) { + this.storage = storage; + } + + // + // messages for the InteropLibrary + // + + @ExportMessage + long getArraySize() { + return storage.length; + } + + @ExportMessage + Object readArrayElement(long index) throws InvalidArrayIndexException { + try { + return storage[Math.toIntExact(index)]; + } catch (ArithmeticException | IndexOutOfBoundsException ex) { + throw InvalidArrayIndexException.create(index); + } + } + + @ExportMessage + boolean isArrayElementReadable(long index) { + var size = storage.length; + return index < size && index >= 0; + } + + @ExportMessage + boolean hasWarnings() { + return false; + } + + @ExportMessage + Warning[] getWarnings(Node location) throws UnsupportedMessageException { + return new Warning[0]; + } + + @ExportMessage + EnsoOnly removeWarnings() throws UnsupportedMessageException { + return this; + } + + @ExportMessage + boolean isLimitReached() { + return false; + } + } + + @ExportLibrary(InteropLibrary.class) + @ExportLibrary(WarningsLibrary.class) + static final class Generic extends Vector { + private final Object storage; + + private Generic(Object storage) { + if (CompilerDirectives.inInterpreter()) { + if (!InteropLibrary.getUncached().hasArrayElements(storage)) { + throw new IllegalStateException("Vector needs array-like delegate, but got: " + storage); + } + } + this.storage = storage; + } + + final Object toArray() { + return this.storage; + } + + // + // messages for the InteropLibrary + // + + @ExportMessage + long getArraySize( + @Cached.Shared(value = "interop") @CachedLibrary(limit = "3") InteropLibrary interop) + throws UnsupportedMessageException { + return interop.getArraySize(storage); + } + + /** + * Handles reading an element by index through the polyglot API. + * + * @param index the index to read + * @return the element value at the provided index + * @throws InvalidArrayIndexException when the index is out of bounds. + */ + @ExportMessage + Object readArrayElement( + long index, + @Cached.Shared(value = "interop") @CachedLibrary(limit = "3") InteropLibrary interop, + @CachedLibrary(limit = "3") WarningsLibrary warnings, + @Cached HostValueToEnsoNode toEnso) + throws InvalidArrayIndexException, UnsupportedMessageException { + var v = interop.readArrayElement(this.storage, index); + if (warnings.hasWarnings(this.storage)) { + Warning[] extracted = warnings.getWarnings(this.storage, null); + if (warnings.hasWarnings(v)) { + v = warnings.removeWarnings(v); + } + return WithWarnings.wrap(EnsoContext.get(interop), toEnso.execute(v), extracted); + } + return toEnso.execute(v); + } + + /** + * Exposes an index validity check through the polyglot API. + * + * @param index the index to check + * @return {@code true} if the index is valid, {@code false} otherwise. + */ + @ExportMessage + boolean isArrayElementReadable( + long index, + @Cached.Shared(value = "interop") @CachedLibrary(limit = "3") InteropLibrary interop) { + try { + var size = interop.getArraySize(storage); + return index < size && index >= 0; + } catch (UnsupportedMessageException e) { + return false; + } + } + + @ExportMessage + boolean hasWarnings( + @Cached.Shared(value = "warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) { + return warnings.hasWarnings(this.storage); + } + + @ExportMessage + Warning[] getWarnings( + Node location, + @Cached.Shared(value = "warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) + throws UnsupportedMessageException { + return warnings.getWarnings(this.storage, location); + } + + @ExportMessage + Generic removeWarnings( + @Cached.Shared(value = "warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) + throws UnsupportedMessageException { + return new Generic(warnings.removeWarnings(this.storage)); + } + + @ExportMessage + boolean isLimitReached( + @Cached.Shared(value = "warnsLib") @CachedLibrary(limit = "3") WarningsLibrary warnings) { + return warnings.isLimitReached(this.storage); + } + } + + @ExportLibrary(value = InteropLibrary.class) + @ExportLibrary(value = WarningsLibrary.class) + static final class Double extends Vector { + private final double[] storage; + + private Double(double[] storage) { + this.storage = storage; + } + + @ExportMessage + long getArraySize() { + return storage.length; + } + + /** + * Handles reading an element by index through the polyglot API. + * + * @param index the index to read + * @return the element value at the provided index + * @throws InvalidArrayIndexException when the index is out of bounds. + */ + @ExportMessage + Object readArrayElement(long index) throws InvalidArrayIndexException { + try { + return storage[Math.toIntExact(index)]; + } catch (ArithmeticException | IndexOutOfBoundsException ex) { + throw InvalidArrayIndexException.create(index); + } + } + + /** + * Exposes an index validity check through the polyglot API. + * + * @param index the index to check + * @return {@code true} if the index is valid, {@code false} otherwise. + */ + @ExportMessage + boolean isArrayElementReadable(long index) { + var size = storage.length; + return index < size && index >= 0; + } + + @ExportMessage + boolean hasWarnings() { + return false; + } + + @ExportMessage + Warning[] getWarnings(Node location) throws UnsupportedMessageException { + return new Warning[0]; + } + + @ExportMessage + Double removeWarnings() { + return this; + } + + @ExportMessage + boolean isLimitReached() { + return false; + } + } + + @ExportLibrary(value = InteropLibrary.class) + @ExportLibrary(value = WarningsLibrary.class) + static final class Long extends Vector { + private final long[] storage; + + private Long(long[] storage) { + this.storage = storage; + } + + @ExportMessage + long getArraySize() { + return storage.length; + } + + @ExportMessage + Object readArrayElement(long index) throws InvalidArrayIndexException { + try { + return storage[Math.toIntExact(index)]; + } catch (ArithmeticException | IndexOutOfBoundsException ex) { + throw InvalidArrayIndexException.create(index); + } + } + + @ExportMessage + boolean isArrayElementReadable(long index) { + var size = storage.length; + return index < size && index >= 0; + } + + @ExportMessage + boolean hasWarnings() { + return false; + } + + @ExportMessage + Warning[] getWarnings(Node location) throws UnsupportedMessageException { + return new Warning[0]; + } + + @ExportMessage + Long removeWarnings() { + return this; + } + + @ExportMessage + boolean isLimitReached() { + return false; + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/Warning.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/Warning.java index d9e71fb4a701..8cbbe72a8d59 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/Warning.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/Warning.java @@ -4,7 +4,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -16,15 +15,16 @@ import java.util.Comparator; import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.Array; import org.enso.interpreter.runtime.data.ArrayRope; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.graalvm.collections.EconomicSet; @Builtin(pkg = "error", stdlibName = "Standard.Base.Warning.Warning") @ExportLibrary(TypesLibrary.class) -public final class Warning implements TruffleObject { +public final class Warning implements EnsoObject { private final Object value; private final Object origin; private final ArrayRope reassignments; @@ -62,9 +62,9 @@ public static Warning create(EnsoContext ctx, Object payload, Object origin) { } @Builtin.Method(description = "Gets the list of locations where the warnings was reassigned.") - public Array getReassignments() { + public EnsoObject getReassignments() { Warning.Reassignment[] reassignmentsArray = reassignments.toArray(Warning.Reassignment[]::new); - return new Array(Arrays.copyOf(reassignmentsArray, reassignmentsArray.length, Object[].class)); + return ArrayLikeHelpers.wrapEnsoObjects(reassignmentsArray); } @Builtin.Method( @@ -92,10 +92,10 @@ public static WithWarnings attach(EnsoContext ctx, Object value, Object warning, autoRegister = false) @Builtin.Specialize @CompilerDirectives.TruffleBoundary - public static Array getAll(WithWarnings value, WarningsLibrary warningsLib) { + public static EnsoObject getAll(WithWarnings value, WarningsLibrary warningsLib) { Warning[] warnings = value.getWarningsArray(warningsLib); sortArray(warnings); - return new Array((Object[]) warnings); + return ArrayLikeHelpers.wrapEnsoObjects(warnings); } @Builtin.Method( @@ -103,17 +103,17 @@ public static Array getAll(WithWarnings value, WarningsLibrary warningsLib) { description = "Gets all the warnings associated with the value.", autoRegister = false) @Builtin.Specialize(fallback = true) - public static Array getAll(Object value, WarningsLibrary warnings) { + public static EnsoObject getAll(Object value, WarningsLibrary warnings) { if (warnings.hasWarnings(value)) { try { Warning[] arr = warnings.getWarnings(value, null); sortArray(arr); - return new Array((Object[]) arr); + return ArrayLikeHelpers.wrapEnsoObjects(arr); } catch (UnsupportedMessageException e) { throw new IllegalStateException(e); } } else { - return new Array(); + return ArrayLikeHelpers.empty(); } } @@ -190,7 +190,7 @@ public String toString() { } @ExportLibrary(InteropLibrary.class) - public static final class Reassignment implements TruffleObject { + public static final class Reassignment implements EnsoObject { private final String methodName; private final SourceSection location; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/WithWarnings.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/WithWarnings.java index 7bba829f1890..b2efcdac37f3 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/WithWarnings.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/WithWarnings.java @@ -2,11 +2,12 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached.Shared; + import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.data.ArrayRope; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -14,14 +15,14 @@ import com.oracle.truffle.api.library.Message; import com.oracle.truffle.api.library.ReflectionLibrary; import com.oracle.truffle.api.nodes.Node; -import org.enso.polyglot.RuntimeOptions; + import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; @ExportLibrary(TypesLibrary.class) @ExportLibrary(WarningsLibrary.class) @ExportLibrary(ReflectionLibrary.class) -public final class WithWarnings implements TruffleObject { +public final class WithWarnings implements EnsoObject { private final EconomicSet warnings; private final Object value; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java index d9a3f513011d..cb74cbf54d42 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java @@ -3,13 +3,13 @@ import java.math.BigInteger; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -18,7 +18,7 @@ /** Internal wrapper for a {@link BigInteger}. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) -public final class EnsoBigInteger implements TruffleObject { +public final class EnsoBigInteger implements EnsoObject { private final BigInteger value; /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/DebugLocalScope.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/DebugLocalScope.java index d75f4914db8a..50f4675a1897 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/DebugLocalScope.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/DebugLocalScope.java @@ -4,7 +4,6 @@ import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; @@ -19,6 +18,7 @@ import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.node.EnsoRootNode; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.error.DataflowError; /** @@ -33,7 +33,7 @@ * */ @ExportLibrary(InteropLibrary.class) -public class DebugLocalScope implements TruffleObject { +public class DebugLocalScope implements EnsoObject { private final EnsoRootNode rootNode; /** All the bindings, including the parent scopes. */ @@ -262,7 +262,7 @@ private MaterializedFrame getProperFrame(MaterializedFrame frame, FramePointer p /** Simple interop wrapper for a list of strings. */ @ExportLibrary(InteropLibrary.class) - static final class ScopeMembers implements TruffleObject { + static final class ScopeMembers implements EnsoObject { private final List memberNames; ScopeMembers(List memberNames) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java index f510a71f251b..66a22ec3d685 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java @@ -1,7 +1,6 @@ package org.enso.interpreter.runtime.scope; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.interop.TruffleObject; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -12,12 +11,13 @@ import java.util.Set; import org.enso.interpreter.runtime.Module; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.error.RedefinedConversionException; import org.enso.interpreter.runtime.error.RedefinedMethodException; /** A representation of Enso's per-file top-level scope. */ -public final class ModuleScope implements TruffleObject { +public final class ModuleScope implements EnsoObject { private final Type associatedType; private final Module module; private Map polyglotSymbols; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/TopLevelScope.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/TopLevelScope.java index 00657f2e0347..ae97ee11de8f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/TopLevelScope.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/TopLevelScope.java @@ -5,7 +5,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; @@ -20,7 +19,8 @@ import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.Module; import org.enso.interpreter.runtime.builtin.Builtins; -import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.type.Types; import org.enso.interpreter.util.ScalaConversions; import org.enso.pkg.Package; @@ -30,7 +30,7 @@ /** Represents the top scope of Enso execution, containing all the importable modules. */ @ExportLibrary(InteropLibrary.class) -public final class TopLevelScope implements TruffleObject { +public final class TopLevelScope implements EnsoObject { private final Builtins builtins; private final PackageRepository packageRepository; @@ -107,8 +107,8 @@ boolean hasMembers() { * @return a collection of all the exported members. */ @ExportMessage - Array getMembers(boolean includeInternal) { - return new Array( + EnsoObject getMembers(boolean includeInternal) { + return ArrayLikeHelpers.wrapStrings( MethodNames.TopScope.GET_MODULE, MethodNames.TopScope.CREATE_MODULE, MethodNames.TopScope.REGISTER_MODULE, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/system/System.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/system/System.java index 29e1dd5d4aca..068415f51fd5 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/system/System.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/system/System.java @@ -12,11 +12,11 @@ import org.apache.commons.lang3.SystemUtils; import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode; import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.data.vector.ArrayLikeCoerceToArrayNode; public class System { @@ -72,7 +72,7 @@ public static Atom createProcess( boolean redirectIn, boolean redirectOut, boolean redirectErr, - @Cached CoerceArrayNode coerce, + @Cached ArrayLikeCoerceToArrayNode coerce, @Cached ExpectStringNode expectStringNode) throws IOException, InterruptedException { Object[] arrArguments = coerce.execute(arguments); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java index bb00714927cf..d1ace8bd1ab7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java @@ -8,9 +8,6 @@ import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.ArrayOverBuffer; -import org.enso.interpreter.runtime.data.ArrayProxy; import org.enso.interpreter.runtime.data.EnsoDate; import org.enso.interpreter.runtime.data.EnsoDateTime; import org.enso.interpreter.runtime.data.EnsoDuration; @@ -20,7 +17,6 @@ import org.enso.interpreter.runtime.data.ManagedResource; import org.enso.interpreter.runtime.data.Ref; import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.data.Vector; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.error.DataflowError; @@ -53,16 +49,12 @@ DataflowError.class, UnresolvedConversion.class, UnresolvedSymbol.class, - Array.class, - ArrayProxy.class, - ArrayOverBuffer.class, EnsoBigInteger.class, ManagedResource.class, ModuleScope.class, Ref.class, PanicException.class, PanicSentinel.class, - Vector.class, EnsoHashMap.class, Warning.class, EnsoFile.class, diff --git a/engine/runtime/src/test/java/org/enso/interpreter/test/MetaObjectTest.java b/engine/runtime/src/test/java/org/enso/interpreter/test/MetaObjectTest.java index 2eea7ea72b22..9efbdd69d410 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/test/MetaObjectTest.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/test/MetaObjectTest.java @@ -96,6 +96,7 @@ public void checkAllConstantGenValuesArePresent() throws Exception { expecting.add(s); } } + expecting.remove(ConstantsGen.ARRAY_LIKE_HELPERS); var w = new StringBuilder(); var f = new StringWriter(); var err = new PrintWriter(f); diff --git a/engine/runtime/src/test/java/org/enso/interpreter/test/ValuesGenerator.java b/engine/runtime/src/test/java/org/enso/interpreter/test/ValuesGenerator.java index 1b4476eba1c1..5ac88390b5b8 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/test/ValuesGenerator.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/test/ValuesGenerator.java @@ -522,12 +522,13 @@ public List periods() { public List arrayLike() { var collect = new ArrayList(); if (languages.contains(Language.ENSO)) { - collect.add(v(null, "", "[1, 2, 3]").type()); - collect.add(v(null, "", "['a', 'b']").type()); - collect.add(v(null, "", "[]").type()); - collect.add(v(null, "", "[1, 2, 3].to_array").type()); - collect.add(v(null, "", "['a', 'b'].to_array").type()); - collect.add(v(null, "", "[].to_array").type()); + var im = "from Standard.Base import Vector"; + collect.add(v(null, im, "[1, 2, 3]").type()); + collect.add(v(null, im, "['a', 'b']").type()); + collect.add(v(null, im, "[]").type()); + collect.add(v(null, im, "[1, 2, 3].to_array").type()); + collect.add(v(null, im, "['a', 'b'].to_array").type()); + collect.add(v(null, im, "[].to_array").type()); collect.add(v(null, """ import Standard.Base.Data.Array_Proxy.Array_Proxy """, "Array_Proxy.new 10 (x -> 2 * x)").type()); diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/ExecuteMethodImplGenerator.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/ExecuteMethodImplGenerator.java index 6b3af7554e70..b582899536a9 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/ExecuteMethodImplGenerator.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/ExecuteMethodImplGenerator.java @@ -116,7 +116,13 @@ private String[] bodyBase(String name, String owner, List param }; case ARRAY: return new String[] { - " return new Array((Object[]) " + qual + "." + name + "(" + paramsApplied + "));" + " return ArrayLikeHelpers.wrapObjects(" + + qual + + "." + + name + + "(" + + paramsApplied + + "));" }; default: if (returnTpe.isValidGuestType()) { diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/MethodNodeClassGenerator.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/MethodNodeClassGenerator.java index 807a1147d2e7..ea8e2b3f31f2 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/MethodNodeClassGenerator.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/MethodNodeClassGenerator.java @@ -6,7 +6,7 @@ import java.util.Arrays; import java.util.List; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.*; +import javax.lang.model.element.Element; import javax.tools.JavaFileObject; import org.enso.interpreter.dsl.Builtin; @@ -148,6 +148,5 @@ private void generateClassHeader(PrintWriter out, String methodName, String desc "org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode", "org.enso.interpreter.runtime.EnsoContext", "org.enso.interpreter.runtime.builtin.Builtins", - "org.enso.interpreter.runtime.data.Array", "org.enso.interpreter.runtime.error.PanicException"); } diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/SpecializedMethodsGenerator.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/SpecializedMethodsGenerator.java index 492801031f42..b6d22cd7fb2d 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/SpecializedMethodsGenerator.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/SpecializedMethodsGenerator.java @@ -278,7 +278,13 @@ protected List specialize( break; case ARRAY: methodBody.add( - " return new Array((Object[]) " + qual + "." + name + "(" + paramsApplied + "));"); + " return ArrayLikeHelpers.wrapObjects(" + + qual + + "." + + name + + "(" + + paramsApplied + + "));"); break; default: if (returnTpe.isValidGuestType()) { diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/TypeWithKind.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/TypeWithKind.java index 3e175cd680ec..4d49b2c5e0a8 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/TypeWithKind.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/builtins/TypeWithKind.java @@ -39,13 +39,14 @@ boolean isValidGuestType() { */ private final static List validGuestTypes = List.of( + "org.enso.interpreter.runtime.data.EnsoObject", "org.enso.interpreter.runtime.callable.atom.Atom", "org.enso.interpreter.runtime.callable.function.Function", - "org.enso.interpreter.runtime.data.Array", - "org.enso.interpreter.runtime.data.Vector", "org.enso.interpreter.runtime.data.hash.EnsoHashMap", - "org.enso.interpreter.runtime.data.ArrayOverBuffer", - "org.enso.interpreter.runtime.data.ArrayProxy", + "org.enso.interpreter.runtime.data.vector.Array", + "org.enso.interpreter.runtime.data.vector.Vector", + "org.enso.interpreter.runtime.data.vector.ArrayOverBuffer", + "org.enso.interpreter.runtime.data.vector.ArrayProxy", "org.enso.interpreter.runtime.data.EnsoFile", "org.enso.interpreter.runtime.data.EnsoDate", "org.enso.interpreter.runtime.data.EnsoDateTime", diff --git a/std-bits/base/src/main/java/org/enso/base/Array_Builder.java b/std-bits/base/src/main/java/org/enso/base/Array_Builder.java deleted file mode 100644 index cae356680345..000000000000 --- a/std-bits/base/src/main/java/org/enso/base/Array_Builder.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.enso.base; - -import java.util.Arrays; -import java.util.List; - -public class Array_Builder { - private static final Object[] EMPTY_ARRAY = new Object[0]; - private final int initialCapacity; - private int size; - private Object primitiveArray; - private Object[] objectArray; - - private Array_Builder(int initialCapacity) { - this.initialCapacity = Math.max(1, initialCapacity); - } - - /** - * This function forces the polyglot conversion of an Enso array into a `byte[]`. This allows for - * asserting that it is a valid `byte[]`. - * - * @param input the converted array. - * @return the `input` unchanged. - */ - public static byte[] ensureByteArray(byte[] input) { - return input; - } - - /** Creates new builder */ - public static Array_Builder newBuilder(int capacity) { - return new Array_Builder<>(capacity); - } - - /** Is the builder empty? */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Adds an element to the builder - * - * @param e the element to add - */ - public void add(T e) { - if (objectArray != null) { - if (size == objectArray.length) { - objectArray = Arrays.copyOf(objectArray, size * 2); - } - objectArray[size++] = e; - } else if (primitiveArray instanceof long[] longArray) { - if (e instanceof Long l) { - if (size == longArray.length) { - primitiveArray = longArray = Arrays.copyOf(longArray, size * 2); - } - longArray[size++] = l; - } else { - objectArray = new Object[longArray.length]; - for (int i = 0; i < size; i++) { - objectArray[i] = longArray[i]; - } - primitiveArray = null; - add(e); - } - } else if (primitiveArray instanceof double[] doubleArray) { - if (e instanceof Double d) { - if (size == doubleArray.length) { - primitiveArray = doubleArray = Arrays.copyOf(doubleArray, size * 2); - } - doubleArray[size++] = d; - } else { - objectArray = new Object[doubleArray.length]; - for (int i = 0; i < size; i++) { - objectArray[i] = doubleArray[i]; - } - primitiveArray = null; - add(e); - } - } else { - assert objectArray == null; - assert primitiveArray == null; - assert size == 0; - if (e instanceof Long l) { - var arr = new long[initialCapacity]; - arr[0] = l; - primitiveArray = arr; - } else if (e instanceof Double d) { - var arr = new double[initialCapacity]; - arr[0] = d; - primitiveArray = arr; - } else { - var arr = new Object[initialCapacity]; - arr[0] = e; - objectArray = arr; - } - size = 1; - } - } - - /** Obtains an element from the builder */ - public Object get(int index) { - if (objectArray != null) { - return objectArray[index]; - } else if (primitiveArray instanceof long[] longArray) { - return longArray[index]; - } else if (primitiveArray instanceof double[] doubleArray) { - return doubleArray[index]; - } else { - throw new ArrayIndexOutOfBoundsException(); - } - } - - /** A temporary workaround to be able to efficiently append an array to `ArrayList`. */ - public void appendTo(List list) { - for (T obj : list) { - add(obj); - } - } - - /** Returns the current array of the builder. */ - public Object toArray() { - if (objectArray != null) { - return objectArray.length == size ? objectArray : Arrays.copyOf(objectArray, size); - } else if (primitiveArray instanceof long[] longArray) { - return longArray.length == size ? longArray : Arrays.copyOf(longArray, size); - } else if (primitiveArray instanceof double[] doubleArray) { - return doubleArray.length == size ? doubleArray : Arrays.copyOf(doubleArray, size); - } else { - return EMPTY_ARRAY; - } - } - - public int getSize() { - return size; - } -} diff --git a/std-bits/base/src/main/java/org/enso/base/Array_Utils.java b/std-bits/base/src/main/java/org/enso/base/Array_Utils.java new file mode 100644 index 000000000000..3d1737625480 --- /dev/null +++ b/std-bits/base/src/main/java/org/enso/base/Array_Utils.java @@ -0,0 +1,16 @@ +package org.enso.base; + +public final class Array_Utils { + private Array_Utils() {} + + /** + * This function forces the polyglot conversion of an Enso array into a `byte[]`. This allows for + * asserting that it is a valid `byte[]`. + * + * @param input the converted array. + * @return the `input` unchanged. + */ + public static byte[] ensureByteArray(byte[] input) { + return input; + } +} diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index 5d27c488f77c..c844666da260 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -788,6 +788,25 @@ type_spec name alter = Test.group name <| Warning.limit_reached sorted . should_equal True spec = + Test.group "Vector builder" <| + Test.specify "empty builder.get" <| + b = Vector.new_builder + e = Panic.catch Index_Out_Of_Bounds (b.at 0) err-> + err.payload + Meta.type_of e . should_equal Index_Out_Of_Bounds + e.index . should_equal 0 + e.length . should_equal 0 + + Test.specify "one number builder.get" <| + b = Vector.new_builder + b.append 32 + e = Panic.catch Index_Out_Of_Bounds (b.at 1) err-> + err.payload + Meta.type_of e . should_equal Index_Out_Of_Bounds + e.index . should_equal 1 + e.length . should_equal 1 + b.at 0 . should_equal 32 + Test.group "Vector/Array equality" <| v1 = [1, 2, 3] a1 = v1.to_array diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso index 5ee80947c82f..3c609b860d8f 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso @@ -1,4 +1,6 @@ +import project.Data.Vector.Vector + @Builtin_Type type Array - at self index = @Builtin_Method "Array.at" - length self = @Builtin_Method "Array.length" + at self index = Vector.at self index + length self = Vector.length self diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso index 7d9c0759bb48..c23ae7496d3a 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso @@ -1,4 +1,10 @@ @Builtin_Type type Vector a from_array array = @Builtin_Method "Vector.from_array" - at self index = @Builtin_Method "Vector.at" + at self index = array_like_at self index + length self = array_like_length self + to_array self = array_like_vector_to_array self + +array_like_at array index = @Builtin_Method "Array_Like_Helpers.at" +array_like_length array = @Builtin_Method "Array_Like_Helpers.length" +array_like_vector_to_array array = @Builtin_Method "Array_Like_Helpers.vector_to_array"