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 2dfd025bd4dda..6cbcbd58adf65 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 @@ -601,8 +601,7 @@ type Vector + : Vector Any -> Vector Any + that = this_len = this.length - arr = Array.new (this_len + that.length) - Array.copy this.to_array 0 arr 0 this_len + arr = Array.clone this.to_array 0 this_len (this_len + that.length) Array.copy that.to_array 0 arr this_len that.length Vector arr @@ -664,8 +663,8 @@ type Vector slice_start = Math.max 0 start slice_end = Math.min this.length end if slice_start >= slice_end then Vector (Array.new 0) else - new_array = Array.new (slice_end - slice_start) - Array.Copy this.to_array start new_array 0 new_array.length + len = slice_end - slice_start + new_array = Array.clone this.to_array slice_start len len Vector new_array ## Creates a new vector with the first `count` elements in `this` removed. @@ -894,8 +893,7 @@ type Vector ## Prepare the destination array that will underlie the vector. We do not want to sort in place on the original vector, as `sort` is not intended to be mutable. - new_vec_arr = Array.new this.length - Array.copy this.to_array 0 new_vec_arr 0 this.length + new_vec_arr = Array.clone this.to_array 0 this.length this.length ## As we want to account for both custom projections and custom comparisons we need to construct a comparator for internal use that @@ -1070,8 +1068,7 @@ type Builder Unsafe.set_atom_field this 1 (this.length + 1) False -> old_array = this.to_array - new_array = Array.new old_array.length*2 - Array.copy old_array 0 new_array 0 old_array.length + new_array = Array.clone this.to_array 0 old_array.length old_array.length*2 Unsafe.set_atom_field this 0 new_array this.append item Nothing @@ -1099,9 +1096,7 @@ type Builder bldr.to_vector to_vector : Vector Any to_vector = - old_array = this.to_array - new_array = Array.new this.length - Array.copy old_array 0 new_array 0 this.length + new_array = Array.clone this.to_array 0 this.length this.length Vector new_array ## UNSTABLE diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java new file mode 100644 index 0000000000000..f25567ed2866e --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java @@ -0,0 +1,154 @@ +package org.enso.interpreter.node.expression.builtin.mutable; + +import com.oracle.truffle.api.dsl.CachedContext; +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.Language; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Builtins; +import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.error.PanicException; + +@BuiltinMethod(type = "Array", name = "clone", description = "Copies one array to another.") +public abstract class CloneNode extends Node { + + static CloneNode build() { + return CloneNodeGen.create(); + } + + abstract Object execute( + Object _this, Object src, long source_index, long source_count, long new_size); + + @Specialization + Object doArray( + Object _this, + Array src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + Array output = new Array(new_size); + System.arraycopy( + src.getItems(), (int) source_index, output.getItems(), 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + byte[] src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + byte[] output = new byte[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + int[] src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + int[] output = new int[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + long[] src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + long[] output = new long[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + char[] src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + char[] output = new char[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + float[] src, + long source_index, + long source_count, + long new_size, + @CachedContext(Language.class) Context ctx) { + float[] output = new float[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization + Object doPolyglotArray( + Object _this, + double[] src, + long source_index, + long new_size, + long source_count, + @CachedContext(Language.class) Context ctx) { + double[] output = new double[(int) new_size]; + System.arraycopy(src, (int) source_index, output, 0, (int) source_count); + return output; + } + + @Specialization(guards = "arrays.hasArrayElements(src)") + Object doPolyglotArray( + Object _this, + Object src, + long source_index, + long new_size, + long source_count, + @CachedLibrary(limit = "3") InteropLibrary arrays, + @CachedContext(Language.class) Context ctx) { + Array dest = new Array(new_size); + try { + for (int i = 0; i < source_count; i++) { + dest.getItems()[i] = arrays.readArrayElement(src, source_index + i); + } + } catch (UnsupportedMessageException e) { + throw new IllegalStateException("Unreachable"); + } catch (InvalidArrayIndexException e) { + throw new PanicException( + ctx.getBuiltins().error().makeInvalidArrayIndexError(src, e.getInvalidIndex()), this); + } + return dest; + } + + @Fallback + Object doOther( + Object _this, + Object src, + long source_index, + long source_count, + long new_size) { + Builtins builtins = lookupContextReference(Language.class).get().getBuiltins(); + throw new PanicException( + builtins.error().makeTypeError(builtins.mutable().array().newInstance(), src, "src"), this); + } +} \ No newline at end of file diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Mutable.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Mutable.java index 3e055e01e2284..a7ab5cd8c5819 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Mutable.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Mutable.java @@ -30,6 +30,7 @@ public Mutable(Language language, ModuleScope scope) { scope.registerMethod(array, "at", GetAtMethodGen.makeFunction(language)); scope.registerMethod(array, "set_at", SetAtMethodGen.makeFunction(language)); scope.registerMethod(array, "copy", CopyMethodGen.makeFunction(language)); + scope.registerMethod(array, "clone", CloneMethodGen.makeFunction(language)); scope.registerMethod(array, "sort", SortMethodGen.makeFunction(language)); ref = new AtomConstructor("Ref", scope).initializeFields(); diff --git a/engine/runtime/src/main/resources/Builtins.enso b/engine/runtime/src/main/resources/Builtins.enso index 8f2bfcfa59162..92aaf9390d34d 100644 --- a/engine/runtime/src/main/resources/Builtins.enso +++ b/engine/runtime/src/main/resources/Builtins.enso @@ -906,6 +906,19 @@ type Array copy src source_index dest dest_index count = @Builtin_Method "Array.copy" + ## Clones from the source array, beginning at the specified position, to + a new destination array. + + Arguments: + - src: The source array. + - source_index: The start position in the src array. + - source_count: Amount to copy from source. + - new_size: Size of new array. + + clone : Array -> Integer -> Integer -> Integer -> Array + clone src source_index source_count new_size = + @Builtin_Method "Array.clone" + ## Gets the element at index in the array this. Arguments: diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index 208114ef8aaf3..402e4d0451deb 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -27,6 +27,9 @@ foreign js generate_js_array = """ spec = Test.group "Vectors" <| + Test.specify "text bytes" <| + "Lore".utf_8 . should_equal [76, 111, 114, 101] + Test.specify "should allow vector creation with a programmatic constructor" <| Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050 diff --git a/test/Tests/src/System/File_Spec.enso b/test/Tests/src/System/File_Spec.enso index 1ce2fb9c8a32e..85d3fd12355b1 100644 --- a/test/Tests/src/System/File_Spec.enso +++ b/test/Tests/src/System/File_Spec.enso @@ -21,6 +21,7 @@ spec = Test.specify "should allow reading a file to byte vector" <| contents = sample_file.read_bytes + IO.println (Meta.get_qualified_type_name contents.to_array) contents.take_start 6 . should_equal [67, 117, 112, 99, 97, 107] Test.specify "should handle exceptions when reading a non-existent file" <| @@ -109,3 +110,4 @@ spec = filtered2 = Enso_Project.data.list name_filter="*/*/*" recursive=True . map .to_text filtered2.should_equal (resolve ["subdirectory/nested/b.txt"]) +main = Test.Suite.run_main here.spec