Skip to content

Commit

Permalink
Clone node experiment
Browse files Browse the repository at this point in the history
  • Loading branch information
jdunkerley committed Mar 2, 2022
1 parent c08ea74 commit 80021aa
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 11 deletions.
17 changes: 6 additions & 11 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 13 additions & 0 deletions engine/runtime/src/main/resources/Builtins.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions test/Tests/src/Data/Vector_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions test/Tests/src/System/File_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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" <|
Expand Down Expand Up @@ -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

0 comments on commit 80021aa

Please sign in to comment.