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 d75187df18f1..1906ac5f8512 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 @@ -382,7 +382,7 @@ type Array `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -421,7 +421,7 @@ type Array `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -668,7 +668,7 @@ type Array `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -891,7 +891,7 @@ type Array `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. 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 2595ea237180..a400acf7280d 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 @@ -679,7 +679,7 @@ type Vector a `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -718,7 +718,7 @@ type Vector a `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -772,7 +772,7 @@ type Vector a `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -1014,7 +1014,7 @@ type Vector a `Map_Error`. - No_Wrap: The first error is thrown, and is not wrapped in `Map_Error`. - - Report_Warning: The result for that element is `Nothing`, + - Report_Warning: The result for that element is `Nothing`, the error is attached as a warning. Currently unimplemented. - Ignore: The result is `Nothing`, and the error is ignored. @@ -1507,17 +1507,16 @@ type Builder ## GROUP Conversions ICON convert Clones the builder into a Vector. - to_vector : Vector Any - to_vector self = + to_vector self -> Vector = ## This creates a fresh copy of the builders storage, so any future changes to the builder will not affect the returned vector. This also reattaches any warnings that were attached to the added values. It attaches them to the whole array, not the individual values. - warnings_vector = Vector.from_polyglot_array self.warnings_java_builder.toArray + warnings_vector = self.warnings_java_builder.toArray Warning.attach_multiple warnings_vector <| - Vector.from_polyglot_array self.elements_java_builder.toArray + self.elements_java_builder.toArray ## PRIVATE Describes an error attached to a value within a `Vector`. The `index` field diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso index fc1260b0e445..0bdd5aac6931 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso @@ -74,7 +74,7 @@ type Warning - wrap_errors: If true, warnings attached to elements in array-likes are wrapped in Map_Error. get_all : Any -> Boolean -> Vector Warning - get_all value wrap_errors:Boolean=False = Vector.from_polyglot_array (get_all_array value wrap_errors) + get_all value wrap_errors:Boolean=False = get_all_vector value wrap_errors ## PRIVATE ADVANCED @@ -306,8 +306,8 @@ attach_with_stacktrace value warning origin = @Builtin_Method "Warning.attach_wi ## PRIVATE Builtin function that gets all the warnings attached to the given value. -get_all_array : Any -> Boolean -> Array Warning -get_all_array value should_wrap = @Builtin_Method "Warning.get_all_array" +get_all_vector : Any -> Boolean -> Vector Warning +get_all_vector value should_wrap = @Builtin_Method "Warning.get_all_vector" ## PRIVATE diff --git a/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/VectorBenchmarks.java b/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/VectorBenchmarks.java index e34c8c0d048e..e44f97fbae51 100644 --- a/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/VectorBenchmarks.java +++ b/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/VectorBenchmarks.java @@ -38,10 +38,15 @@ public void initializeBenchmark(BenchmarkParams params) throws Exception { import Standard.Base.Data.Vector.Builder import Standard.Base.Data.Vector.Vector import Standard.Base.Data.Array_Proxy.Array_Proxy + from Standard.Base.Data.Boolean import False avg arr = - sum acc i = if i == arr.length then acc else - @Tail_Call sum (acc + arr.at i) i+1 + sum acc i = + stop = i == arr.length + if stop then acc else + value = arr.at i + both = acc + value + @Tail_Call sum both i+1 (sum 0 0) / arr.length fibarr size modulo = diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java index 27f5bd7f0744..38b944b0e9fb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java @@ -490,7 +490,11 @@ public Optional getBuiltinFunction( if (atomNodes == null) { return Optional.empty(); } - LoadedBuiltinMethod builtin = atomNodes.get(methodName).get(); + var supply = atomNodes.get(methodName); + if (supply == null) { + return Optional.empty(); + } + LoadedBuiltinMethod builtin = supply.get(); if (builtin == null) { return Optional.empty(); } 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 index b06b89bb1fb1..cda3cf51812f 100644 --- 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 @@ -12,17 +12,20 @@ import com.oracle.truffle.api.nodes.Node; import java.util.Arrays; import org.enso.interpreter.runtime.data.EnsoObject; +import org.enso.interpreter.runtime.error.WarningsLibrary; @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; + /** becomes {@code true} when a non trivial value is being added to the builder */ + private boolean nonTrivialEnsoValue; + private ArrayBuilder(int initialCapacity) { this.initialCapacity = Math.max(1, initialCapacity); } @@ -41,14 +44,21 @@ boolean isEmpty() { * Adds an element to the builder * * @param e the element to add + * @param warnings library to check for values with warnings */ - void add(Object e) { - if (objectArray != null) { - if (size == objectArray.length) { - CompilerDirectives.transferToInterpreter(); - objectArray = Arrays.copyOf(objectArray, size * 2); + void add(Object e, WarningsLibrary warnings) { + if (!nonTrivialEnsoValue) { + if (warnings.hasWarnings(e)) { + nonTrivialEnsoValue = true; + } else { + var isEnsoValue = e instanceof EnsoObject || e instanceof Long || e instanceof Double; + if (!isEnsoValue) { + nonTrivialEnsoValue = true; + } } - objectArray[size++] = e; + } + if (objectArray != null) { + addToObjectArray(e); } else if (primitiveArray instanceof long[] longArray) { if (e instanceof Long l) { if (size == longArray.length) { @@ -63,7 +73,7 @@ void add(Object e) { objectArray[i] = longArray[i]; } primitiveArray = null; - add(e); + addToObjectArray(e); } } else if (primitiveArray instanceof double[] doubleArray) { if (e instanceof Double d) { @@ -79,29 +89,41 @@ void add(Object e) { objectArray[i] = doubleArray[i]; } primitiveArray = null; - add(e); + addToObjectArray(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; + switch (e) { + case Long l -> { + var arr = new long[initialCapacity]; + arr[0] = l; + primitiveArray = arr; + } + case Double d -> { + var arr = new double[initialCapacity]; + arr[0] = d; + primitiveArray = arr; + } + default -> { + var arr = new Object[initialCapacity]; + arr[0] = e; + objectArray = arr; + } } size = 1; } } + private void addToObjectArray(Object e) { + if (size == objectArray.length) { + CompilerDirectives.transferToInterpreter(); + objectArray = Arrays.copyOf(objectArray, size * 2); + } + objectArray[size++] = e; + } + /** Obtains an element from the builder */ private Object get(int index, Node node) { try { @@ -121,7 +143,7 @@ private Object get(int index, Node node) { } /** Returns the current array of the builder. */ - Object toArray() { + private Object toArray() { if (objectArray != null) { return objectArray.length == size ? objectArray : Arrays.copyOf(objectArray, size); } else if (primitiveArray instanceof long[] longArray) { @@ -129,7 +151,7 @@ Object toArray() { } else if (primitiveArray instanceof double[] doubleArray) { return doubleArray.length == size ? doubleArray : Arrays.copyOf(doubleArray, size); } else { - return EMPTY_ARRAY; + return null; } } @@ -138,12 +160,16 @@ int getSize() { } @ExportMessage - Object invokeMember(String name, Object[] args, @CachedLibrary(limit = "3") InteropLibrary iop) + Object invokeMember( + String name, + Object[] args, + @CachedLibrary(limit = "3") InteropLibrary iop, + @CachedLibrary(limit = "3") WarningsLibrary warnings) throws UnknownIdentifierException, UnsupportedTypeException, UnsupportedMessageException { return switch (name) { case "isEmpty" -> isEmpty(); case "add" -> { - add(args[0]); + add(args[0], warnings); yield this; } case "appendTo" -> { @@ -151,7 +177,7 @@ Object invokeMember(String name, Object[] args, @CachedLibrary(limit = "3") Inte for (var i = 0; i < len; i++) { try { var e = iop.readArrayElement(args[0], i); - add(e); + add(e, warnings); } catch (InvalidArrayIndexException ex) { throw UnsupportedTypeException.create(args); } @@ -169,16 +195,7 @@ Object invokeMember(String name, Object[] args, @CachedLibrary(limit = "3") Inte 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(Array.wrap((Object[]) arr)); - } + case "toArray" -> asVector(); default -> throw UnknownIdentifierException.create(name); }; } @@ -207,4 +224,19 @@ EnsoObject getMembers(boolean includeInternal) { String toDisplayString(boolean ignore) { return "Array_Builder"; } + + Object asVector() { + var res = toArray(); + if (res instanceof long[] longs) { + return Vector.fromLongArray(longs); + } + if (res instanceof double[] doubles) { + return Vector.fromDoubleArray(doubles); + } + if (nonTrivialEnsoValue) { + return Vector.fromInteropArray(Array.wrap((Object[]) res)); + } else { + return Vector.fromEnsoOnlyArray((Object[]) res); + } + } } 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 index 54506b25c7c4..0e93ae4680c4 100644 --- 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 @@ -90,35 +90,14 @@ public static Object vectorFromFunction( @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(Array.wrap((Object[]) res)); - } else { - return Vector.fromEnsoOnlyArray((Object[]) res); + target.add(value, warnings); } + return target.asVector(); } @Builtin.Method( @@ -166,4 +145,12 @@ public static EnsoObject asVectorWithCheckAt(Object... arr) { public static EnsoObject asVectorFromArray(Object storage) { return Vector.fromInteropArray(storage); } + + public static EnsoObject asVectorEnsoObjects(EnsoObject... arr) { + return Vector.fromEnsoOnlyArray(arr); + } + + public static EnsoObject asVectorEmpty() { + return Vector.fromEnsoOnlyArray(null); + } } 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 index 9542719e0e0c..40b8cd5d052c 100644 --- 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 @@ -24,6 +24,10 @@ @ExportLibrary(TypesLibrary.class) @Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector") abstract class Vector implements EnsoObject { + private static final Vector EMPTY_LONG = new Long(new long[0]); + private static final Vector EMPTY_DOUBLE = new Double(new double[0]); + private static final Vector EMPTY_VECTOR = new EnsoOnly(new Object[0]); + @ExportMessage boolean hasArrayElements() { return true; @@ -112,15 +116,27 @@ static Vector fromInteropArray(Object arr) { } static Vector fromLongArray(long[] arr) { - return new Long(arr); + if (arr == null || arr.length == 0) { + return EMPTY_LONG; + } else { + return new Long(arr); + } } static Vector fromDoubleArray(double[] arr) { - return new Double(arr); + if (arr == null || arr.length == 0) { + return EMPTY_DOUBLE; + } else { + return new Double(arr); + } } - static Object fromEnsoOnlyArray(Object[] arr) { - return new EnsoOnly(arr); + static Vector fromEnsoOnlyArray(Object[] arr) { + if (arr == null || arr.length == 0) { + return EMPTY_VECTOR; + } else { + return new EnsoOnly(arr); + } } @ExportLibrary(InteropLibrary.class) 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 c4549e02bedf..e1ff24d35c94 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 @@ -88,7 +88,7 @@ public static WithWarnings attach(EnsoContext ctx, Object value, Object warning, } @Builtin.Method( - name = "get_all_array", + name = "get_all_vector", description = "Gets all the warnings associated with the value.", autoRegister = false) @Builtin.Specialize @@ -97,11 +97,11 @@ public static EnsoObject getAll( WithWarnings value, boolean shouldWrap, WarningsLibrary warningsLib) { Warning[] warnings = value.getWarningsArray(warningsLib, shouldWrap); sortArray(warnings); - return ArrayLikeHelpers.wrapEnsoObjects(warnings); + return ArrayLikeHelpers.asVectorEnsoObjects(warnings); } @Builtin.Method( - name = "get_all_array", + name = "get_all_vector", description = "Gets all the warnings associated with the value.", autoRegister = false) @Builtin.Specialize(fallback = true) @@ -110,12 +110,12 @@ public static EnsoObject getAll(Object value, boolean shouldWrap, WarningsLibrar try { Warning[] warnings = warningsLib.getWarnings(value, null, shouldWrap); sortArray(warnings); - return ArrayLikeHelpers.wrapEnsoObjects(warnings); + return ArrayLikeHelpers.asVectorEnsoObjects(warnings); } catch (UnsupportedMessageException e) { throw EnsoContext.get(warningsLib).raiseAssertionPanic(warningsLib, null, e); } } else { - return ArrayLikeHelpers.empty(); + return ArrayLikeHelpers.asVectorEmpty(); } }