Skip to content

Commit

Permalink
All Vector operations shall be applicable on java.util.ArrayList (#6642)
Browse files Browse the repository at this point in the history
Fixes #6609 by
- e380e64 - running whole `Vector_Spec` on `java.util.ArrayList`
- 9b1229f - introducing a node to handle interop values

# Important Notes
Contains additional DSL processor fix:
- 415623d - to not crash the compiler, but to properly report compiler error
  • Loading branch information
JaroslavTulach authored May 11, 2023
1 parent 866501f commit 1302b69
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ type Array
map_with_index self function = Vector.map_with_index self function

slice : Integer -> Integer -> Vector Any
slice self start end = @Builtin_Method "Array.slice"
slice self start end = Vector.slice self start end

## Returns the first element of the array that satisfies the predicate or
`if_missing` if no elements of the array satisfy it.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.enso.interpreter.node.expression.builtin.immutable;

import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.error.PanicException;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;

@BuiltinMethod(type = "Vector", name = "slice", description = "Returns a slice of this Vector.")
public abstract class SliceArrayVectorNode extends Node {
SliceArrayVectorNode() {}

public static SliceArrayVectorNode build() {
return SliceArrayVectorNodeGen.create();
}

abstract Object execute(Object self, long start, long end);

@Specialization
Object executeArray(Array self, long start, long end) {
return Array.slice(self, start, end, self.length());
}

@Specialization
Object executeVector(
Vector self, long start, long end, @CachedLibrary(limit = "3") InteropLibrary iop) {
try {
return Array.slice(self, start, end, self.length(iop));
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
throw unsupportedMessageException(self);
}
}

@Specialization(replaces = {"executeArray", "executeVector"})
Object executeArrayLike(
Object self, long start, long end, @CachedLibrary(limit = "3") InteropLibrary iop) {
try {
long len = iop.getArraySize(self);
return Array.slice(self, start, end, len);
} catch (UnsupportedMessageException ex) {
CompilerDirectives.transferToInterpreter();
throw unsupportedMessageException(self);
}
}

private PanicException unsupportedMessageException(Object self) throws PanicException {
var ctx = EnsoContext.get(this);
var arrayType = ctx.getBuiltins().array();
throw new PanicException(
ctx.getBuiltins().error().makeTypeError(arrayType, self, "self"), this);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
package org.enso.interpreter.runtime.data;

import java.util.Arrays;

import org.enso.interpreter.dsl.Builtin;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.error.Warning;
import org.enso.interpreter.runtime.error.WarningsLibrary;
import org.enso.interpreter.runtime.error.WithWarnings;
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
import org.graalvm.collections.EconomicSet;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.interop.InteropLibrary;
Expand Down Expand Up @@ -130,13 +140,18 @@ public static Array empty() {
return allocate(0);
}

@Builtin.Method(name = "slice", description = "Returns a slice of this Array.")
@Builtin.Specialize
@Builtin.WrapException(from = UnsupportedMessageException.class)
public final Object slice(long start, long end, InteropLibrary interop)
throws UnsupportedMessageException {
var slice = ArraySlice.createOrNull(this, start, length(), end);
return slice == null ? this : slice;
/**
* Takes a slice from an array like object.
*
* @param self array like object
* @param start start of the slice
* @param end end of the slice
* @param len the length of the array
* @return an array-like object representing the slice
*/
public static Object slice(Object self, long start, long end, long len) {
var slice = ArraySlice.createOrNull(self, start, len, end);
return slice == null ? self : slice;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
package org.enso.interpreter.runtime.data;

import org.enso.interpreter.dsl.Builtin;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.error.DataflowError;
import org.enso.interpreter.runtime.error.Warning;
import org.enso.interpreter.runtime.error.WarningsLibrary;
import org.enso.interpreter.runtime.error.WithWarnings;
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.interop.ArityException;
Expand All @@ -11,17 +21,7 @@
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;

import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.Builtin;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.error.DataflowError;
import org.enso.interpreter.runtime.error.Warning;
import org.enso.interpreter.runtime.error.WarningsLibrary;
import org.enso.interpreter.runtime.error.WithWarnings;
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;

@ExportLibrary(InteropLibrary.class)
@ExportLibrary(TypesLibrary.class)
Expand Down Expand Up @@ -67,15 +67,6 @@ public final Object toArray() {
return this.storage;
}

@Builtin.Method(name = "slice", description = "Returns a slice of this Vector.")
@Builtin.Specialize
@Builtin.WrapException(from = UnsupportedMessageException.class)
public final Vector slice(long start, long end, InteropLibrary interop)
throws UnsupportedMessageException {
var slice = ArraySlice.createOrNull(storage, start, length(interop), end);
return slice == null ? this : slice;
}

@Builtin.Method(description = "Returns the length of this Vector.")
@Builtin.Specialize
@Builtin.WrapException(from = UnsupportedMessageException.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
package org.enso.interpreter.runtime.error;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.interop.*;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;
import org.enso.interpreter.node.BaseNode.TailStatus;
import org.enso.interpreter.node.callable.IndirectInvokeMethodNode;
import org.enso.interpreter.node.callable.InvokeCallableNode.ArgumentsExecutionMode;
Expand All @@ -23,10 +14,22 @@
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
import org.enso.interpreter.runtime.state.State;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.interop.ExceptionType;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;

/** An exception type for user thrown panic exceptions. */
@ExportLibrary(value = InteropLibrary.class, delegateTo = "payload")
@ExportLibrary(TypesLibrary.class)
public class PanicException extends AbstractTruffleException {
public final class PanicException extends AbstractTruffleException {
final Object payload;
String cacheMessage;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package org.enso.interpreter.dsl.model;

import org.enso.interpreter.dsl.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.util.*;
import javax.tools.Diagnostic.Kind;

import org.enso.interpreter.dsl.AcceptsError;
import org.enso.interpreter.dsl.AcceptsWarning;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.dsl.Suspend;

/** A domain-specific representation of a builtin method. */
public class MethodDefinition {
Expand All @@ -26,7 +39,7 @@ public class MethodDefinition {
private final Set<String> imports;
private final boolean needsCallerInfo;
private final boolean needsFrame;
private final String constructorExpression;
private final Object constructorExpression;

/**
* Creates a new instance of this class.
Expand Down Expand Up @@ -70,7 +83,7 @@ public String[] aliases() {
}
}

private String initConstructor(TypeElement element) {
private Object initConstructor(TypeElement element) {
boolean useBuild =
element.getEnclosedElements().stream()
.anyMatch(
Expand All @@ -88,7 +101,7 @@ private String initConstructor(TypeElement element) {
} else {
boolean isClassAbstract = element.getModifiers().contains(Modifier.ABSTRACT);
if (isClassAbstract) {
throw new RuntimeException(
return new RuntimeException(
"Class "
+ element.getSimpleName()
+ " is abstract, and has no static `build()` method.");
Expand Down Expand Up @@ -153,6 +166,11 @@ private List<ArgumentDefinition> initArguments(ExecutableElement method) {
* @return whether the definition is fully valid.
*/
public boolean validate(ProcessingEnvironment processingEnvironment) {
if (this.constructorExpression instanceof Exception ex) {
processingEnvironment.getMessager().printMessage(Kind.ERROR, ex.getMessage(), element);
return false;
}

boolean argsValid = arguments.stream().allMatch(arg -> arg.validate(processingEnvironment));

return argsValid;
Expand Down Expand Up @@ -214,7 +232,7 @@ public boolean needsFrame() {
}

public String getConstructorExpression() {
return constructorExpression;
return (String) constructorExpression;
}

public boolean isStatic() {
Expand Down
17 changes: 13 additions & 4 deletions test/Tests/src/Data/Vector_Spec.enso
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from Standard.Base import all
from Standard.Base.Data.Array_Proxy import Array_Proxy
import Standard.Base.Data.Vector.Empty_Error
import Standard.Base.Errors.Common.Incomparable_Values
import Standard.Base.Errors.Common.Index_Out_Of_Bounds
Expand All @@ -13,6 +14,8 @@ from Standard.Base.Data.Index_Sub_Range.Index_Sub_Range import While, By_Index,
from Standard.Test import Test, Test_Suite
import Standard.Test.Extensions

polyglot java import java.util.ArrayList

type T
Value a b

Expand Down Expand Up @@ -265,9 +268,9 @@ type_spec name alter = Test.group name <|
boolvec.filter Filter_Condition.Is_False . should_equal [False]

Test.specify "should filter elements with indices" <|
alter [0, 10, 2, 2] . filter_with_index (==) . should_equal [0, 2]
(alter [0, 10, 2, 2] . filter_with_index (==)) . should_equal [0, 2]
(alter [1, 2, 3, 4] . filter_with_index ix-> _-> ix < 2) . should_equal [1, 2]
alter ([1, 2, 3, 4] . filter_with_index ix-> _-> if ix == 1 then Error.throw <| My_Error.Value "foo" else True) . should_fail_with My_Error
(alter [1, 2, 3, 4] . filter_with_index ix-> _-> if ix == 1 then Error.throw <| My_Error.Value "foo" else True) . should_fail_with My_Error

Test.specify "should partition elements" <|
alter [1, 2, 3, 4, 5] . partition (x -> x % 2 == 0) . should_equal <| Pair.new [2, 4] [1, 3, 5]
Expand Down Expand Up @@ -752,7 +755,13 @@ spec =
[True, False, 'a'].pretty . should_equal "[True, False, 'a']"
[Foo.Value True].pretty . should_equal "[(Foo.Value True)]"

type_spec "Use Vector as vectors" (x -> x)
type_spec "Use Array as vectors" (x -> x.to_array)
type_spec "Use Vector as vectors" identity
type_spec "Use Array as vectors" (v -> v.to_array)
type_spec "Use Java ArrayList as vectors" v->
arr = ArrayList.new
v.each (x -> arr.add x)
arr
type_spec "Use Array_Proxy as vectors" v->
Array_Proxy.new v.length (ix -> v.at ix)

main = Test_Suite.run_main spec

0 comments on commit 1302b69

Please sign in to comment.