mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 13:15:52 +03:00
Directly allocate warnings asVectorEnsoObjects (#10143)
This commit is contained in:
parent
af4177e61f
commit
9632f04e9b
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -38,10 +38,15 @@ public class VectorBenchmarks {
|
||||
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 =
|
||||
|
@ -490,7 +490,11 @@ public final class Builtins {
|
||||
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();
|
||||
}
|
||||
|
@ -12,17 +12,20 @@ import com.oracle.truffle.api.library.ExportMessage;
|
||||
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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
* 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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
}
|
||||
|
||||
/** 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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
} 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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
}
|
||||
|
||||
@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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
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 @@ final class ArrayBuilder implements EnsoObject {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,35 +90,14 @@ public final class ArrayLikeHelpers {
|
||||
@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 final class ArrayLikeHelpers {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,10 @@ import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||
@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 @@ abstract class Vector implements EnsoObject {
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -88,7 +88,7 @@ public final class Warning implements EnsoObject {
|
||||
}
|
||||
|
||||
@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 final class Warning implements EnsoObject {
|
||||
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 final class Warning implements EnsoObject {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user