From 9f27dab9b5b8b5b981b7dc40863b688d1d12b795 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 26 Jan 2022 11:46:41 +0000 Subject: [PATCH 01/20] Expanded benchmarks --- test/Benchmarks/src/Vector.enso | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/Benchmarks/src/Vector.enso b/test/Benchmarks/src/Vector.enso index 1138d781a016..55ec7df69229 100644 --- a/test/Benchmarks/src/Vector.enso +++ b/test/Benchmarks/src/Vector.enso @@ -21,8 +21,18 @@ make_random_vec n = main = random_vec = here.make_random_vec here.vector_size - + random_vec_2 = here.make_random_vec 100000 + + Bench.measure (Base.Vector.new here.vector_size i->i) "New Vector" here.iter_size here.num_iterations + Bench.measure (random_vec + [1]) "Append Single" here.iter_size here.num_iterations + Bench.measure (random_vec + random_vec_2) "Append Large" here.iter_size here.num_iterations + Bench.measure (random_vec.sum) "Sum" here.iter_size here.num_iterations + Bench.measure ((random_vec.drop_start 20).sum) "Drop First 20 and Sum" here.iter_size here.num_iterations + Bench.measure ((random_vec.drop_end 20).sum) "Drop Last 20 and Sum" here.iter_size here.num_iterations Bench.measure (random_vec.filter (x -> x % 3 == 1)) "Filter" here.iter_size here.num_iterations + Bench.measure (random_vec.filter_with_index (i->x -> (i+x) % 3 == 1)) "Filter With Index" here.iter_size here.num_iterations + Bench.measure (random_vec.partition (x -> x % 3 == 1)) "Partition" here.iter_size here.num_iterations + Bench.measure (random_vec.partition_with_index (i->x -> (i+x) % 3 == 1)) "Partition With Index" here.iter_size here.num_iterations stateful_fun x = s = State.get Number From 8ca19369d3eda5b97ea7c9cff1edfd0e3eddcadf Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 26 Jan 2022 12:42:19 +0000 Subject: [PATCH 02/20] Update Builder and append --- .../Base/0.0.0-dev/src/Data/Vector.enso | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) 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 14243fb6d3c7..786f8f34b691 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 @@ -231,10 +231,7 @@ type Vector [1, 2, 3, 4, 5].exists (> 3) exists : (Any -> Boolean) -> Boolean exists predicate = - len = this.length - go idx found = if found || (idx >= len) then found else - @Tail_Call go idx+1 (predicate (this.unsafe_at idx)) - go 0 False + 0.up_to this.length . exists (idx -> (predicate (this.unsafe_at idx))) ## Returns the first element of the vector that satisfies the predicate or if no elements of the vector satisfy the predicate, it throws nothing. @@ -572,10 +569,8 @@ type Vector + that = this_len = this.length arr = Array.new (this_len + that.length) - 0.up_to this_len . each i-> - arr.set_at i (this.unsafe_at i) - this.length.up_to arr.length . each i-> - arr.set_at i (that.unsafe_at i-this_len) + Array.copy this.to_array 0 arr 0 this_len + Array.copy that.to_array 0 arr this_len that.length Vector arr ## Add `element` to the beginning of `this` vector. @@ -1027,9 +1022,7 @@ type Builder False -> old_array = this.to_array new_array = Array.new old_array.length*2 - 0.up_to this.length . each i-> - new_array.set_at i (old_array.at i) - Nothing + Array.copy old_array 0 new_array 0 old_array.length Unsafe.set_atom_field this 0 new_array this.append item Nothing @@ -1042,10 +1035,7 @@ type Builder exists : (Any -> Boolean) -> Boolean exists predicate = - len = this.length - go idx found = if found || (idx >= len) then found else - @Tail_Call go idx+1 (predicate (this.to_array.at idx)) - go 0 False + 0.up_to this.length . exists (idx -> (predicate (this.to_array.at idx))) ## Converts this builder to a vector containing all the appended elements. @@ -1062,9 +1052,7 @@ type Builder to_vector = old_array = this.to_array new_array = Array.new this.length - 0.up_to this.length . each i-> - new_array.set_at i (old_array.at i) - Nothing + Array.copy old_array 0 new_array 0 this.length Vector new_array ## UNSTABLE From 1879cc4732557d8ffa478aa665b117d8f6525ea9 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 26 Jan 2022 14:47:18 +0000 Subject: [PATCH 03/20] Slice, Take, Drop... Tweak for reduce and all --- .../Base/0.0.0-dev/src/Data/Vector.enso | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) 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 786f8f34b691..7ed3d46c73fe 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 @@ -198,7 +198,10 @@ type Vector reduce : (Any -> Any -> Any) -> Any ! Empty_Error reduce function = case this.not_empty of - True -> this.tail.fold this.head function + True -> if this.length == 1 then this.unsafe_at 0 else + arr = this.to_array + f = acc -> ix -> function acc (arr.at ix) + 1.up_to this.length . fold (this.unsafe_at 0) f False -> Error.throw Empty_Error ## Computes the sum of the values in the vector. @@ -281,7 +284,7 @@ type Vector [-1, 1, 5, 8].all (< 0) all : (Any -> Boolean) -> Boolean - all predicate = this.fold True (l -> r -> l && predicate r) + all predicate = (this.exists (r -> (predicate r).not)).not ## Checks whether this vector contains a given value as an element. @@ -615,6 +618,26 @@ type Vector if this.length == 1 then prefix + this.unsafe_at 0 + suffix else prefix + this.unsafe_at 0 + (1.up_to this.length . fold "" acc-> i-> acc + separator + this.unsafe_at i) + suffix + ## Creates a new vector with the skipping elements until `start` and then + continuing for `length` elements. + + Arguments: + - start: The number of elements to drop from the start of `this`. + - length: The number of elements for the sub-vector. + + > Example + Remove the first 2 elements then take 5 from the vector. + + [1, 2, 3, 4, 5, 6, 7, 8].slice 2 5 + slice : Integer -> Integer -> Vector Any + slice start length = + if start > this.length then Vector (Array.new 0) else + slice_length = Math.min (this.length - start) length + if slice_length == 0 then Vector (Array.new 0) else + new_array = Array.new slice_length + Array.Copy this.to_array start new_array 0 slice_length + Vector new_array + ## Creates a new vector with the first `count` elements in `this` removed. Arguments: @@ -625,8 +648,7 @@ type Vector [1, 2, 3, 4, 5].drop_start 1 drop_start : Integer -> Vector Any - drop_start count = if count >= this.length then here.new 0 (x -> x) else - here.new (this.length - count) (i -> this.unsafe_at i+count) + drop_start count = this.slice count (this.length - count) ## Creates a new vector with the last `count` elements in `this` removed. @@ -638,8 +660,7 @@ type Vector [1, 2, 3, 4, 5].drop_end 2 drop_end : Integer -> Vector Any - drop_end count = if count >= this.length then here.new 0 (x -> x) else - this.take_start (this.length - count) + drop_end count = this.slice 0 (this.length - count) ## Creates a new vector, consisting of the first `count` elements on the left of `this`. @@ -652,8 +673,7 @@ type Vector [1, 2, 3, 4, 5].take_start 2 take_start : Integer -> Vector Any - take_start count = if count >= this.length then this else - here.new count this.at + take_start count = this.slice 0 count ## Creates a new vector, consisting of the last `count` elements on the right of `this`. @@ -666,8 +686,7 @@ type Vector [1, 2, 3, 4, 5].take_end 3 take_end : Integer -> Vector Any - take_end count = if count >= this.length then this else - this.drop_start (this.length - count) + take_end count = this.slice (this.length - count) count ## Performs a pair-wise operation passed in `function` on consecutive elements of `this` and `that`. From f6e2978424ecb5002e6c1591972b23efb95d5400 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 26 Jan 2022 17:39:03 +0000 Subject: [PATCH 04/20] Each With Index Filter and Partition tweaks --- .../Base/0.0.0-dev/src/Data/Vector.enso | 68 +++++++++++++------ test/Tests/src/Data/Vector_Spec.enso | 2 + 2 files changed, 51 insertions(+), 19 deletions(-) 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 7ed3d46c73fe..d262446b09db 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 @@ -184,6 +184,24 @@ type Vector f = acc -> ix -> function acc (arr.at ix) 0.up_to this.length . fold init f + ## Combines all the elements of the vector, by iteratively applying the + passed function with next elements of the vector. + + Arguments: + - init: The initial value for the fold. + - function: A function taking the current value, an index and an item + and combining them. + + > Example + Compute the sum of all of the elements and indexes in a vector. + + [0, 1, 2] . fold 0 (s->i->e->s+i+e) + fold_with_index : Any -> (Any -> Integer -> Any -> Any) -> Any + fold_with_index init function = + arr = this.to_array + f = acc -> ix -> function acc ix (arr.at ix) + 0.up_to this.length . fold init f + ## Combines all the elements of a non-empty vector using a binary operation. Arguments: @@ -346,12 +364,8 @@ type Vector [0, 10, 2, 2].filter (==) == [0, 2] filter_with_index : (Integer -> Any -> Boolean) -> Vector Any filter_with_index predicate = - acc = this.fold (Pair here.new_builder 0) acc-> elem-> - builder = acc.first - ix = acc.second - new_builder = if predicate ix elem then builder.append elem else builder - Pair new_builder ix+1 - builder = acc.first + builder = this.fold_with_index here.new_builder builder-> ix-> elem-> + if predicate ix elem then builder.append elem else builder builder.to_vector ## Partitions the vector into vectors of elements which satisfy a given @@ -372,15 +386,15 @@ type Vector Splitting a vector into even and odd elements. [1, 2, 3, 4, 5].partition (x -> x % 2 == 0) == (Pair [2, 4] [1, 3, 5]) - partition : (Any -> Boolean) -> Vector Any + partition : (Any -> Boolean) -> Pair Vector Any Vector Any partition predicate = - acc = this.fold (Pair here.new_builder here.new_builder) acc-> elem-> + pair = this.fold (Pair here.new_builder here.new_builder) acc-> elem-> case predicate elem of True -> Pair (acc.first.append elem) acc.second False -> Pair acc.first (acc.second.append elem) - acc.map .to_vector + pair.map .to_vector ## Partitions the vector into vectors of elements which satisfy a given predicate and ones that do not. @@ -400,17 +414,13 @@ type Vector Splitting a vector into elements at even and odd positions. ["a", "b", "c", "d"].partition_with_index (ix -> _ -> ix % 2 == 0) == (Pair ["a", "c"] ["b", "d"]) - partition_with_index : (Integer -> Any -> Boolean) -> Vector Any + partition_with_index : (Integer -> Any -> Boolean) -> Pair Vector Any Vector Any partition_with_index predicate = - acc = this.fold (Partition_Accumulator here.new_builder here.new_builder 0) acc-> elem-> - case predicate acc.ix elem of - True -> - Partition_Accumulator (acc.true_builder.append elem) acc.false_builder acc.ix+1 - False -> - Partition_Accumulator acc.true_builder (acc.false_builder.append elem) acc.ix+1 - case acc of - Partition_Accumulator true_builder false_builder _ -> - Pair true_builder.to_vector false_builder.to_vector + pair = this.fold_with_index (Pair here.new_builder here.new_builder) acc-> ix-> elem-> + case predicate ix elem of + True -> Pair (acc.first.append elem) acc.second + False -> Pair acc.first (acc.second.append elem) + pair.map .to_vector ## Applies a function to each element of the vector, returning the vector of results. @@ -499,6 +509,26 @@ type Vector 0.up_to this.length . each ix-> f (this.unsafe_at ix) + ## Applies a function to each element of the vector. + + Arguments: + - function: A function to apply that takes an index and an item. + + The function is called with both the element index as well as the + element itself. + + Unlike `map`, this method does not return the individual results, + therefore it is only useful for side-effecting computations. + + > Example + Print each element in the vector to standard output. + + [1, 2, 3, 4, 5] . each_with_index (ix->elem-> IO.println Pair ix elem) + each_with_index : (Integer -> Any -> Any) -> Nothing + each_with_index f = + 0.up_to this.length . each ix-> + f ix (this.unsafe_at ix) + ## Reverses the vector, returning a vector with the same elements, but in the opposite order. diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index d1bea3fad323..b6f3098298bc 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -117,6 +117,8 @@ spec = Test.group "Vectors" <| Test.specify "should partition elements" <| [1, 2, 3, 4, 5].partition (x -> x % 2 == 0) . should_equal <| Pair [2, 4] [1, 3, 5] ([1, 2, 3, 4].partition x-> if x == 1 then Error.throw <| My_Error "foo" else True) . should_fail_with My_Error + + Test.specify "should partition elements with indices" <| ["a", "b", "c", "d"].partition_with_index (ix -> _ -> ix % 2 == 0) == (Pair ["a", "c"] ["b", "d"]) ["a", "b", "c", "d"].partition_with_index (ix -> _ -> if ix % 2 == 0 then Error.throw <| My_Error "foo" else True) . should_fail_with My_Error From 4a38b5aea2c9c0cb47a943b99fa1aae8e876fae0 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 27 Jan 2022 22:02:42 +0000 Subject: [PATCH 05/20] Rename slice to take --- .../Base/0.0.0-dev/src/Data/Vector.enso | 36 +++++++++---------- test/Tests/src/Data/Vector_Spec.enso | 1 + 2 files changed, 19 insertions(+), 18 deletions(-) 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 d262446b09db..2dfd025bd4dd 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 @@ -649,24 +649,24 @@ type Vector prefix + this.unsafe_at 0 + (1.up_to this.length . fold "" acc-> i-> acc + separator + this.unsafe_at i) + suffix ## Creates a new vector with the skipping elements until `start` and then - continuing for `length` elements. + continuing until `end` index. Arguments: - - start: The number of elements to drop from the start of `this`. - - length: The number of elements for the sub-vector. + - start: The index of the first element to include. + - end: The index to stop slicing at. > Example - Remove the first 2 elements then take 5 from the vector. - - [1, 2, 3, 4, 5, 6, 7, 8].slice 2 5 - slice : Integer -> Integer -> Vector Any - slice start length = - if start > this.length then Vector (Array.new 0) else - slice_length = Math.min (this.length - start) length - if slice_length == 0 then Vector (Array.new 0) else - new_array = Array.new slice_length - Array.Copy this.to_array start new_array 0 slice_length - Vector new_array + Remove the first 2 elements then continue until index 5 from the vector. + + [1, 2, 3, 4, 5, 6, 7, 8].slice 2 5 == [3, 4, 5] + take : Integer -> Integer -> Vector Any + take start end = + 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 + Vector new_array ## Creates a new vector with the first `count` elements in `this` removed. @@ -678,7 +678,7 @@ type Vector [1, 2, 3, 4, 5].drop_start 1 drop_start : Integer -> Vector Any - drop_start count = this.slice count (this.length - count) + drop_start count = this.take count this.length ## Creates a new vector with the last `count` elements in `this` removed. @@ -690,7 +690,7 @@ type Vector [1, 2, 3, 4, 5].drop_end 2 drop_end : Integer -> Vector Any - drop_end count = this.slice 0 (this.length - count) + drop_end count = this.take 0 (this.length - count) ## Creates a new vector, consisting of the first `count` elements on the left of `this`. @@ -703,7 +703,7 @@ type Vector [1, 2, 3, 4, 5].take_start 2 take_start : Integer -> Vector Any - take_start count = this.slice 0 count + take_start count = this.take 0 count ## Creates a new vector, consisting of the last `count` elements on the right of `this`. @@ -716,7 +716,7 @@ type Vector [1, 2, 3, 4, 5].take_end 3 take_end : Integer -> Vector Any - take_end count = this.slice (this.length - count) count + take_end count = this.take (this.length - count) this.length ## Performs a pair-wise operation passed in `function` on consecutive elements of `this` and `that`. diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index b6f3098298bc..208114ef8aaf 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -185,6 +185,7 @@ spec = Test.group "Vectors" <| vec = [1, 2, 3, 4, 5, 6] first_four = [1, 2, 3, 4] last_four = [3, 4, 5, 6] + vec.take 2 4 . should_equal [3, 4] vec.drop_start 2 . should_equal last_four vec.drop_end 2 . should_equal first_four vec.take_start 4 . should_equal first_four From 3b168f67e14cbb7ed6abeff60f6c948394c93558 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 27 Jan 2022 22:14:07 +0000 Subject: [PATCH 06/20] ChangeLog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 971cc9043179..18b395b03300 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ - [Implemented initial `Table.group_by` function on Standard.Table][3305] - [Implemented `Text.pad` and `Text.trim`][3309] - [Updated `Text.repeat` and added `*` operator shorthand][3310] +- [General improved Vector performance and new `Vector.each_with_index`, + `Vector.fold_with_index` and `Vector.take` methods.][3236] [debug-shortcuts]: https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug @@ -94,6 +96,7 @@ [3305]: https://github.com/enso-org/enso/pull/3305 [3309]: https://github.com/enso-org/enso/pull/3309 [3310]: https://github.com/enso-org/enso/pull/3310 +[3236]: https://github.com/enso-org/enso/pull/3236 #### Enso Compiler From 0b07c14d0187343a31bc0e84e2a4e2d6f545b156 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Mon, 31 Jan 2022 11:20:55 +0000 Subject: [PATCH 07/20] Clone node experiment --- .../Base/0.0.0-dev/src/Data/Vector.enso | 17 +- .../expression/builtin/mutable/CloneNode.java | 154 ++++++++++++++++++ .../interpreter/runtime/builtin/Mutable.java | 1 + .../runtime/src/main/resources/Builtins.enso | 13 ++ test/Tests/src/Data/Vector_Spec.enso | 3 + test/Tests/src/System/File_Spec.enso | 2 + 6 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java 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 2dfd025bd4dd..6cbcbd58adf6 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 000000000000..f25567ed2866 --- /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 3e055e01e228..a7ab5cd8c581 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 8f2bfcfa5916..92aaf9390d34 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 208114ef8aaf..402e4d0451de 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 1ce2fb9c8a32..85d3fd12355b 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 From 1e68f867221207254291f2ad82518aaa11c70782 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 08:44:19 +0000 Subject: [PATCH 08/20] Remove Clone idea Revert + and take to use iterative approach for now --- .../Base/0.0.0-dev/src/Data/Vector.enso | 19 ++- .../expression/builtin/mutable/CloneNode.java | 154 ------------------ .../interpreter/runtime/builtin/Mutable.java | 1 - .../runtime/src/main/resources/Builtins.enso | 13 -- 4 files changed, 13 insertions(+), 174 deletions(-) delete mode 100644 engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java 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 6cbcbd58adf6..01a9f2087815 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,11 @@ type Vector + : Vector Any -> Vector Any + that = this_len = this.length - arr = Array.clone this.to_array 0 this_len (this_len + that.length) - Array.copy that.to_array 0 arr this_len that.length + arr = Array.new (this_len + that.length) + 0.up_to this_len . each i-> + arr.set_at i (this.unsafe_at i) + this.length.up_to arr.length . each i-> + arr.set_at i (that.unsafe_at i-this_len) Vector arr ## Add `element` to the beginning of `this` vector. @@ -664,7 +667,7 @@ type Vector slice_end = Math.min this.length end if slice_start >= slice_end then Vector (Array.new 0) else len = slice_end - slice_start - new_array = Array.clone this.to_array slice_start len len + here.new len (i -> this.unsafe_at (i+slice_start)) Vector new_array ## Creates a new vector with the first `count` elements in `this` removed. @@ -893,7 +896,8 @@ 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.clone this.to_array 0 this.length this.length + new_vec_arr = Array.new this.length + Array.copy this.to_array 0 new_vec_arr 0 this.length ## As we want to account for both custom projections and custom comparisons we need to construct a comparator for internal use that @@ -1068,7 +1072,8 @@ type Builder Unsafe.set_atom_field this 1 (this.length + 1) False -> old_array = this.to_array - new_array = Array.clone this.to_array 0 old_array.length old_array.length*2 + new_array = Array.new old_array.length*2 + Array.copy old_arrays 0 new_array 0 old_array.length Unsafe.set_atom_field this 0 new_array this.append item Nothing @@ -1096,7 +1101,9 @@ type Builder bldr.to_vector to_vector : Vector Any to_vector = - new_array = Array.clone this.to_array 0 this.length this.length + old_array = this.to_array + new_array = Array.new this.length + Array.copy old_arrays 0 new_array 0 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 deleted file mode 100644 index f25567ed2866..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/mutable/CloneNode.java +++ /dev/null @@ -1,154 +0,0 @@ -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 a7ab5cd8c581..3e055e01e228 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,7 +30,6 @@ 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 92aaf9390d34..8f2bfcfa5916 100644 --- a/engine/runtime/src/main/resources/Builtins.enso +++ b/engine/runtime/src/main/resources/Builtins.enso @@ -906,19 +906,6 @@ 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: From c992991383b8e09f9b210b0eda54f3d8b8ef47ad Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 10:43:37 +0000 Subject: [PATCH 09/20] Fix issues --- .../lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 01a9f2087815..33011d001737 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 @@ -668,7 +668,6 @@ type Vector if slice_start >= slice_end then Vector (Array.new 0) else len = slice_end - slice_start here.new len (i -> this.unsafe_at (i+slice_start)) - Vector new_array ## Creates a new vector with the first `count` elements in `this` removed. @@ -1073,7 +1072,7 @@ type Builder False -> old_array = this.to_array new_array = Array.new old_array.length*2 - Array.copy old_arrays 0 new_array 0 old_array.length + Array.copy old_array 0 new_array 0 old_array.length Unsafe.set_atom_field this 0 new_array this.append item Nothing @@ -1103,7 +1102,7 @@ type Builder to_vector = old_array = this.to_array new_array = Array.new this.length - Array.copy old_arrays 0 new_array 0 this.length + Array.copy old_array 0 new_array 0 this.length Vector new_array ## UNSTABLE From 062fa4f134cf4696f7549f35438a01252395dcad Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 12:28:55 +0000 Subject: [PATCH 10/20] Workaround polyglot issue --- .../Base/0.0.0-dev/src/Data/Vector.enso | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) 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 33011d001737..c5cdcb4429e1 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 @@ -588,6 +588,13 @@ type Vector eq_at i = this.unsafe_at i == that.unsafe_at i if this.length == that.length then 0.up_to this.length . all eq_at else False + ## Copy the backing Array to an Enso Array + copy_array : Array + copy_array start_index dest_array dest_start length = + case Builtins.Meta.is_polyglot this.to_array of + True -> 0.up_to length . each i->(dest_array.set_at (i+dest_start) (this.to_array.at i+start_index)) + False -> Array.copy this.to_array start_index dest_array dest_start length + ## Concatenates two vectors, resulting in a new vector, containing all the elements of `this`, followed by all the elements of `that`. @@ -602,10 +609,8 @@ type Vector + that = this_len = this.length arr = Array.new (this_len + that.length) - 0.up_to this_len . each i-> - arr.set_at i (this.unsafe_at i) - this.length.up_to arr.length . each i-> - arr.set_at i (that.unsafe_at i-this_len) + this.copy_array 0 arr 0 this_len + that.copy_array 0 arr this_len that.length Vector arr ## Add `element` to the beginning of `this` vector. @@ -666,8 +671,11 @@ 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 - len = slice_end - slice_start - here.new len (i -> this.unsafe_at (i+slice_start)) + if (slice_start == 0) && (slice_end == this.length) then this else + len = slice_end - slice_start + arr = Array.new len + this.copy_array slice_start arr 0 len + Vector arr ## Creates a new vector with the first `count` elements in `this` removed. @@ -896,7 +904,7 @@ type Vector 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 + this.copy_array 0 new_vec_arr 0 this.length ## As we want to account for both custom projections and custom comparisons we need to construct a comparator for internal use that From cfdc960df6f58fc0b36af1260a63fa2c923c8f38 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 15:00:22 +0000 Subject: [PATCH 11/20] Add test for sorting a polyglot array --- test/Tests/src/Data/Vector_Spec.enso | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index 402e4d0451de..499e4326c1af 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -345,4 +345,9 @@ spec = Test.group "Vectors" <| Test.specify "should return a vector containing only unique elements up to some criteria" <| [Pair 1 "a", Pair 2 "b", Pair 1 "c"] . distinct (on = _.first) . should_equal [Pair 1 "a", Pair 2 "b"] + Test.specify "should be able to sort a polyglot vector" <| + input = "beta".utf_8 + expected = "abet".utf_8 + input.sort . should_equal expected + main = Test.Suite.run_main here.spec From 4a573d052bc17ffd55454b0e6242056d803b4a5d Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 16:22:39 +0000 Subject: [PATCH 12/20] Add test for sorting a polyglot array --- .../lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 8 +++++--- test/Tests/src/Data/Vector_Spec.enso | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) 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 c5cdcb4429e1..0e2597cee70f 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 @@ -470,8 +470,7 @@ type Vector length = this.fold 0 acc-> elem-> acc + elem.length arr = Array.new length this.fold 0 i-> vec-> - # TODO could use Array.copy here, if it was safe... - vec.map_with_index j-> elem-> arr.set_at i+j elem + vec.copy_array 0 arr i vec.length i + vec.length Vector arr @@ -588,7 +587,10 @@ type Vector eq_at i = this.unsafe_at i == that.unsafe_at i if this.length == that.length then 0.up_to this.length . all eq_at else False - ## Copy the backing Array to an Enso Array + ## PRIVATE + Copy the backing Array to an Enso Array + TODO This is a workaround for the issue with polyglot Array.copy + https://www.pivotaltracker.com/story/show/181122542 copy_array : Array copy_array start_index dest_array dest_start length = case Builtins.Meta.is_polyglot this.to_array of diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index 499e4326c1af..3b49200e20b7 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -148,6 +148,7 @@ spec = Test.group "Vectors" <| [[1]].flatten . should_equal [1] [[[1], [2, 3]], [[4]]].flatten . should_equal [[1], [2, 3], [4]] [["a", 2], [], [[[3]]], [T 1 2, 44]].flatten . should_equal ["a", 2, [[3]], T 1 2, 44] + (["polyglot", " ", "array"].map .utf_8).flatten . should_equal "polyglot array".utf_8 Test.specify "should allow applying a function to each element" <| vec = [1, 2, 3, 4] From 7720904bd59dc3e507d63fc4727906d8610ce012 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 16:25:24 +0000 Subject: [PATCH 13/20] Revert debugging change --- test/Tests/src/System/File_Spec.enso | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/Tests/src/System/File_Spec.enso b/test/Tests/src/System/File_Spec.enso index 85d3fd12355b..93e652a719f6 100644 --- a/test/Tests/src/System/File_Spec.enso +++ b/test/Tests/src/System/File_Spec.enso @@ -21,7 +21,6 @@ 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,5 +108,3 @@ 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 From 5c01bf645b383c8c2df2117ffb42c3c3439282d5 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 16:57:13 +0000 Subject: [PATCH 14/20] Change flat_map to use flatten --- .../lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) 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 0e2597cee70f..a19375ff94ec 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 @@ -450,13 +450,7 @@ type Vector [0, 1, 2] . flat_map (n -> Vector.fill n n) flat_map : (Any -> Vector Any) -> Vector Any flat_map function = - mapped = this.map function - length = mapped.fold 0 acc-> elem-> acc + elem.length - arr = Array.new length - mapped.fold 0 i-> vec-> - vec.map_with_index j-> elem-> arr.set_at i+j elem - i + vec.length - Vector arr + this.map function . flatten ## Transforms a vector of vectors into a vector of inner elements - removes one layer of nesting from a stack of nested vectors. From c1eae124563dab69d6451dee3f6d3372c0cbf8e2 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 17:03:17 +0000 Subject: [PATCH 15/20] Update distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Radosław Waśko --- distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a19375ff94ec..4a268de9dde5 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 @@ -386,7 +386,7 @@ type Vector Splitting a vector into even and odd elements. [1, 2, 3, 4, 5].partition (x -> x % 2 == 0) == (Pair [2, 4] [1, 3, 5]) - partition : (Any -> Boolean) -> Pair Vector Any Vector Any + partition : (Any -> Boolean) -> Pair (Vector Any) (Vector Any) partition predicate = pair = this.fold (Pair here.new_builder here.new_builder) acc-> elem-> case predicate elem of From 83661f1c57a334c6032582dd53715c9e5ff64b0c Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Wed, 2 Mar 2022 17:03:25 +0000 Subject: [PATCH 16/20] Update distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Radosław Waśko --- distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4a268de9dde5..74cf77c023b7 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 @@ -414,7 +414,7 @@ type Vector Splitting a vector into elements at even and odd positions. ["a", "b", "c", "d"].partition_with_index (ix -> _ -> ix % 2 == 0) == (Pair ["a", "c"] ["b", "d"]) - partition_with_index : (Integer -> Any -> Boolean) -> Pair Vector Any Vector Any + partition_with_index : (Integer -> Any -> Boolean) -> Pair (Vector Any) (Vector Any) partition_with_index predicate = pair = this.fold_with_index (Pair here.new_builder here.new_builder) acc-> ix-> elem-> case predicate ix elem of From b2a3b0d410ce4619fe126a7e9a41345a7a619dce Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 3 Mar 2022 10:34:10 +0000 Subject: [PATCH 17/20] Move to static method --- .../0.0.0-dev/src/Data/Array/Extensions.enso | 10 ++++++++++ .../Base/0.0.0-dev/src/Data/Vector.enso | 20 +++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso index 3dfeeb48b9ab..e1bb1f95a6bc 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso @@ -1,4 +1,5 @@ from Standard.Base import all +from Standard.Builtins import Builtins ## UNSTABLE ADVANCED @@ -17,3 +18,12 @@ Array.to_default_visualization_data : Text Array.to_default_visualization_data = Vector.Vector this . to_default_visualization_data +## PRIVATE + Copy the backing Array to an Enso Array + TODO This is a workaround for the issue with polyglot Array.copy + https://www.pivotaltracker.com/story/show/181122542 +Array.copy_to : Array->Integer->Array->Integer->Integer +Array.copy_to src_array src_start dest_array dest_start length = + case Builtins.Meta.is_polyglot src_array of + True -> 0.up_to length . each i->(dest_array.set_at (i+dest_start) (src_array.at i+src_start)) + False -> Array.copy src_array src_start dest_array dest_start length 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 74cf77c023b7..86e8e6fe7b8d 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 @@ -464,7 +464,7 @@ type Vector length = this.fold 0 acc-> elem-> acc + elem.length arr = Array.new length this.fold 0 i-> vec-> - vec.copy_array 0 arr i vec.length + Array.copy_to vec.to_array 0 arr i vec.length i + vec.length Vector arr @@ -581,16 +581,6 @@ type Vector eq_at i = this.unsafe_at i == that.unsafe_at i if this.length == that.length then 0.up_to this.length . all eq_at else False - ## PRIVATE - Copy the backing Array to an Enso Array - TODO This is a workaround for the issue with polyglot Array.copy - https://www.pivotaltracker.com/story/show/181122542 - copy_array : Array - copy_array start_index dest_array dest_start length = - case Builtins.Meta.is_polyglot this.to_array of - True -> 0.up_to length . each i->(dest_array.set_at (i+dest_start) (this.to_array.at i+start_index)) - False -> Array.copy this.to_array start_index dest_array dest_start length - ## Concatenates two vectors, resulting in a new vector, containing all the elements of `this`, followed by all the elements of `that`. @@ -605,8 +595,8 @@ type Vector + that = this_len = this.length arr = Array.new (this_len + that.length) - this.copy_array 0 arr 0 this_len - that.copy_array 0 arr this_len that.length + Array.copy_to this.to_array 0 arr 0 this_len + Array.copy_to that.to_array 0 arr this_len that.length Vector arr ## Add `element` to the beginning of `this` vector. @@ -670,7 +660,7 @@ type Vector if (slice_start == 0) && (slice_end == this.length) then this else len = slice_end - slice_start arr = Array.new len - this.copy_array slice_start arr 0 len + Array.copy_to this.to_array slice_start arr 0 len Vector arr ## Creates a new vector with the first `count` elements in `this` removed. @@ -900,7 +890,7 @@ type Vector 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 - this.copy_array 0 new_vec_arr 0 this.length + Array.copy_to this.to_array 0 new_vec_arr 0 this.length ## As we want to account for both custom projections and custom comparisons we need to construct a comparator for internal use that From 14d656a147f883b482b248f7f6ae78dd0175b3c1 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 3 Mar 2022 12:57:10 +0000 Subject: [PATCH 18/20] Fix Array.Copy --- .../Base/0.0.0-dev/src/Data/Array/Extensions.enso | 10 ---------- .../Standard/Base/0.0.0-dev/src/Data/Vector.enso | 10 +++++----- .../node/expression/builtin/mutable/CopyNode.java | 13 ++++++++----- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso index e1bb1f95a6bc..c22476f3788b 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso @@ -17,13 +17,3 @@ from Standard.Builtins import Builtins Array.to_default_visualization_data : Text Array.to_default_visualization_data = Vector.Vector this . to_default_visualization_data - -## PRIVATE - Copy the backing Array to an Enso Array - TODO This is a workaround for the issue with polyglot Array.copy - https://www.pivotaltracker.com/story/show/181122542 -Array.copy_to : Array->Integer->Array->Integer->Integer -Array.copy_to src_array src_start dest_array dest_start length = - case Builtins.Meta.is_polyglot src_array of - True -> 0.up_to length . each i->(dest_array.set_at (i+dest_start) (src_array.at i+src_start)) - False -> Array.copy src_array src_start dest_array dest_start length 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 86e8e6fe7b8d..3dbbe73e94fb 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 @@ -464,7 +464,7 @@ type Vector length = this.fold 0 acc-> elem-> acc + elem.length arr = Array.new length this.fold 0 i-> vec-> - Array.copy_to vec.to_array 0 arr i vec.length + Array.copy vec.to_array 0 arr i vec.length i + vec.length Vector arr @@ -595,8 +595,8 @@ type Vector + that = this_len = this.length arr = Array.new (this_len + that.length) - Array.copy_to this.to_array 0 arr 0 this_len - Array.copy_to that.to_array 0 arr this_len that.length + Array.copy this.to_array 0 arr 0 this_len + Array.copy that.to_array 0 arr this_len that.length Vector arr ## Add `element` to the beginning of `this` vector. @@ -660,7 +660,7 @@ type Vector if (slice_start == 0) && (slice_end == this.length) then this else len = slice_end - slice_start arr = Array.new len - Array.copy_to this.to_array slice_start arr 0 len + Array.copy this.to_array slice_start arr 0 len Vector arr ## Creates a new vector with the first `count` elements in `this` removed. @@ -890,7 +890,7 @@ type Vector 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_to this.to_array 0 new_vec_arr 0 this.length + Array.copy this.to_array 0 new_vec_arr 0 this.length ## As we want to account for both custom projections and custom comparisons we need to construct a comparator for internal use that 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/node/expression/builtin/mutable/CopyNode.java index 4043300acf11..8559f8a5adfa 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/node/expression/builtin/mutable/CopyNode.java @@ -1,5 +1,6 @@ package org.enso.interpreter.node.expression.builtin.mutable; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -10,6 +11,7 @@ import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.Language; import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.builtin.Builtins; import org.enso.interpreter.runtime.data.Array; @@ -48,24 +50,25 @@ Object doPolyglotArray( long dest_index, long count, @CachedLibrary(limit = "3") InteropLibrary arrays, - @CachedContext(Language.class) Context ctx) { + @Cached HostValueToEnsoNode hostValueToEnsoNode) { try { for (int i = 0; i < count; i++) { - dest.getItems()[(int) dest_index + i] = arrays.readArrayElement(src, source_index + i); + dest.getItems()[(int) dest_index + i] = hostValueToEnsoNode.execute( + 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); + Context.get(this).getBuiltins().error().makeInvalidArrayIndexError(src, e.getInvalidIndex()), this); } - return ctx.getBuiltins().nothing().newInstance(); + return Context.get(this).getBuiltins().nothing().newInstance(); } @Fallback Object doOther( Object _this, Object src, long source_index, Array dest, long dest_index, long count) { - Builtins builtins = lookupContextReference(Language.class).get().getBuiltins(); + Builtins builtins = Context.get(this).getBuiltins(); throw new PanicException( builtins.error().makeTypeError(builtins.mutable().array().newInstance(), src, "src"), this); } From 13711fb17ebe2d454369a4f2e89b88579e839527 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 3 Mar 2022 13:04:08 +0000 Subject: [PATCH 19/20] Update distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso Co-authored-by: Marcin Kostrzewa --- distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3dbbe73e94fb..1f293a03d7ef 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 @@ -302,7 +302,7 @@ type Vector [-1, 1, 5, 8].all (< 0) all : (Any -> Boolean) -> Boolean - all predicate = (this.exists (r -> (predicate r).not)).not + all predicate = this . exists (predicate >> .not) . not ## Checks whether this vector contains a given value as an element. From 12c81f3d880a140f57c24fceb763778b149d0128 Mon Sep 17 00:00:00 2001 From: James Dunkerley Date: Thu, 3 Mar 2022 13:05:53 +0000 Subject: [PATCH 20/20] Update Extensions.enso --- .../lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso | 1 - 1 file changed, 1 deletion(-) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso index c22476f3788b..caa2b106f2f8 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array/Extensions.enso @@ -1,5 +1,4 @@ from Standard.Base import all -from Standard.Builtins import Builtins ## UNSTABLE ADVANCED