mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 08:08:34 +03:00
Implement sorting for Vector
(#1349)
This commit is contained in:
parent
de817af655
commit
2c12a18b25
@ -102,8 +102,3 @@ Decimal.parse : Text -> Decimal | Nothing
|
|||||||
Decimal.parse text =
|
Decimal.parse text =
|
||||||
Panic.recover (Double.parseDouble [text]) . catch (_ -> Nothing)
|
Panic.recover (Double.parseDouble [text]) . catch (_ -> Nothing)
|
||||||
|
|
||||||
## Compare two numbers.
|
|
||||||
Number.compare_to : Number -> Ordering
|
|
||||||
Number.compare_to that = if this == that then Ordering.Equal else
|
|
||||||
if this > that then Ordering.Greater else Ordering.Less
|
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
from Base import all
|
from Base import all
|
||||||
|
|
||||||
|
from Builtins import Less, Equal, Greater
|
||||||
|
|
||||||
|
from Builtins export Less, Equal, Greater
|
||||||
|
|
||||||
## Types representing the ordering of values.
|
## Types representing the ordering of values.
|
||||||
|
|
||||||
These are intended to be returned from the `compare_to` function, that has a
|
These are intended to be returned from the `compare_to` function, that has a
|
||||||
@ -9,8 +13,15 @@ from Base import all
|
|||||||
`that`. So, if `this` is greater than `that`, you should return `Greater.`
|
`that`. So, if `this` is greater than `that`, you should return `Greater.`
|
||||||
type Ordering
|
type Ordering
|
||||||
## An ordering where a compared value is less than another.
|
## An ordering where a compared value is less than another.
|
||||||
type Less
|
Less
|
||||||
## An ordering where a compared value is equal to another.
|
## An ordering where a compared value is equal to another.
|
||||||
type Equal
|
Equal
|
||||||
## An ordering where a compared value is greater than another.
|
## An ordering where a compared value is greater than another.
|
||||||
type Greater
|
Greater
|
||||||
|
|
||||||
|
## Converts the ordering to the signed notion of ordering based on integers.
|
||||||
|
to_sign : Integer
|
||||||
|
to_sign = case this of
|
||||||
|
Less -> -1
|
||||||
|
Equal -> 0
|
||||||
|
Greater -> 1
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
from Builtins import Array
|
from Builtins import Array
|
||||||
from Base import all
|
from Base import all
|
||||||
|
|
||||||
import Base.Data.Vector.Sort
|
|
||||||
|
|
||||||
## Creates a new vector of the given length, initializing elements using
|
## Creates a new vector of the given length, initializing elements using
|
||||||
the provided constructor function.
|
the provided constructor function.
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ new length constructor =
|
|||||||
created by:
|
created by:
|
||||||
Vector.fill length=50 item=42
|
Vector.fill length=50 item=42
|
||||||
fill : Number -> Any -> Vector
|
fill : Number -> Any -> Vector
|
||||||
fill length item =
|
fill length ~item =
|
||||||
arr = Array.new length
|
arr = Array.new length
|
||||||
0.up_to length . each ix-> arr.set_at ix item
|
0.up_to length . each ix-> arr.set_at ix item
|
||||||
Vector arr
|
Vector arr
|
||||||
@ -407,10 +405,7 @@ type Vector
|
|||||||
rest : Vector | Nothing
|
rest : Vector | Nothing
|
||||||
rest = this.tail
|
rest = this.tail
|
||||||
|
|
||||||
## PRIVATE
|
## Sort the Vector.
|
||||||
Doesn't work yet.
|
|
||||||
|
|
||||||
Sort the Vector.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
- `on`: A projection from the element type to the value of that element
|
- `on`: A projection from the element type to the value of that element
|
||||||
@ -420,10 +415,26 @@ type Vector
|
|||||||
- `order`: The order in which the vector elements are sorted.
|
- `order`: The order in which the vector elements are sorted.
|
||||||
|
|
||||||
By default, elements are sorted in ascending order, using the comparator
|
By default, elements are sorted in ascending order, using the comparator
|
||||||
`>`. A custom comparator may be passed to the sort function.
|
`compare_to`. A custom comparator may be passed to the sort function.
|
||||||
|
|
||||||
This implements a stable sort, meaning that items that compare the same
|
This is a stable sort, meaning that items that compare the same will not
|
||||||
will not have their order changed.
|
have their order changed by the sorting process.
|
||||||
|
|
||||||
|
The complexities for this sort are:
|
||||||
|
- *Worst-Case Time:* `O(n * log n)`
|
||||||
|
- *Best-Case Time:* `O(n)`
|
||||||
|
- *Average Time:* `O(n * log n)`
|
||||||
|
- *Worst-Case Space:* `O(n)` additional
|
||||||
|
|
||||||
|
? Implementation Note
|
||||||
|
The sort implementation is based upon an adaptive, iterative mergesort
|
||||||
|
that requires far fewer than `n * log(n)` comparisons when the vector
|
||||||
|
is partially sorted. When the vector is randomly ordered, the
|
||||||
|
performance is equivalent to a standard mergesort.
|
||||||
|
|
||||||
|
It takes equal advantage of ascending and descending runs in the array,
|
||||||
|
making it much simpler to merge two or more sorted arrays: simply
|
||||||
|
concatenate them and sort.
|
||||||
|
|
||||||
> Example
|
> Example
|
||||||
Sorting a vector of numbers.
|
Sorting a vector of numbers.
|
||||||
@ -434,7 +445,22 @@ type Vector
|
|||||||
[Pair 1 2, Pair -1 8].sort (_.first) (order = Sort_Order.Descending)
|
[Pair 1 2, Pair -1 8].sort (_.first) (order = Sort_Order.Descending)
|
||||||
sort : (Any -> Any) -> (Any -> Any -> Ordering) -> Sort_Order -> Vector
|
sort : (Any -> Any) -> (Any -> Any -> Ordering) -> Sort_Order -> Vector
|
||||||
sort (on = x -> x) (by = (_.compare_to _)) (order = Sort_Order.Ascending) =
|
sort (on = x -> x) (by = (_.compare_to _)) (order = Sort_Order.Ascending) =
|
||||||
Sort.run this on by order
|
## 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
|
||||||
|
this.to_array.copy 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
|
||||||
|
does both.
|
||||||
|
comp_ascending l r = by (on l) (on r)
|
||||||
|
comp_descending l r = by (on r) (on l)
|
||||||
|
compare = if order == Sort_Order.Ascending then comp_ascending else comp_descending
|
||||||
|
|
||||||
|
new_vec_arr.sort compare
|
||||||
|
|
||||||
|
Vector new_vec_arr
|
||||||
|
|
||||||
## A builder type for Enso vectors.
|
## A builder type for Enso vectors.
|
||||||
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
from Base import all
|
|
||||||
|
|
||||||
# TODO [AA] Implement vector sorting.
|
|
||||||
|
|
||||||
## PRIVATE
|
|
||||||
|
|
||||||
Execute the sort.
|
|
||||||
|
|
||||||
In the use-cases we anticipate for Enso, we can see `sort` being run over
|
|
||||||
both partially-sorted data and random data.
|
|
||||||
|
|
||||||
TODO [AA] Explain why we chose this sort.
|
|
||||||
run : Vector -> (Any -> Any) -> (Any -> Any -> Ordering) -> Sort_Order -> Vector
|
|
||||||
run vec _ _ _ = vec
|
|
||||||
|
|
@ -40,5 +40,5 @@ from Base.Data.Text.Extensions export Text
|
|||||||
from Base.Error.Extensions export all
|
from Base.Error.Extensions export all
|
||||||
from Base.Meta.Enso_Project export all
|
from Base.Meta.Enso_Project export all
|
||||||
from Base.Polyglot.Java export all
|
from Base.Polyglot.Java export all
|
||||||
from Builtins export all hiding Meta
|
from Builtins export all hiding Meta, Less, Equal, Greater, Ordering
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
Function resolveMethodOnArray(Context context, UnresolvedSymbol symbol) {
|
Function resolveMethodOnArray(Context context, UnresolvedSymbol symbol) {
|
||||||
return symbol.resolveFor(
|
return symbol.resolveFor(
|
||||||
context.getBuiltins().mutable().constructor(), context.getBuiltins().any());
|
context.getBuiltins().mutable().array(), context.getBuiltins().any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.mutable;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
||||||
|
import org.enso.interpreter.node.callable.InvokeCallableNode.ArgumentsExecutionMode;
|
||||||
|
import org.enso.interpreter.node.callable.InvokeCallableNode.DefaultsExecutionMode;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
import org.enso.interpreter.runtime.state.data.EmptyMap;
|
||||||
|
|
||||||
|
@NodeInfo(
|
||||||
|
shortName = "sortComparator",
|
||||||
|
description = "The implementation of the comparator for Array sorting.")
|
||||||
|
public abstract class ComparatorNode extends Node {
|
||||||
|
private @Child InvokeCallableNode invokeNode;
|
||||||
|
|
||||||
|
public static ComparatorNode build() {
|
||||||
|
return ComparatorNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparatorNode() {
|
||||||
|
CallArgumentInfo[] callArguments = {new CallArgumentInfo(), new CallArgumentInfo()};
|
||||||
|
invokeNode =
|
||||||
|
InvokeCallableNode.build(
|
||||||
|
callArguments, DefaultsExecutionMode.EXECUTE, ArgumentsExecutionMode.PRE_EXECUTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract int execute(VirtualFrame frame, Object comparator, Object l, Object r);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
int execute(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Object comparator,
|
||||||
|
Object l,
|
||||||
|
Object r,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("ctxRef.get().getBuiltins().ordering().newLess()") Atom less,
|
||||||
|
@Cached("ctxRef.get().getBuiltins().ordering().newEqual()") Atom equal,
|
||||||
|
@Cached("ctxRef.get().getBuiltins().ordering().newGreater()") Atom greater) {
|
||||||
|
Stateful result = invokeNode.execute(comparator, frame, EmptyMap.create(), new Object[] {l, r});
|
||||||
|
Object atom = result.getValue();
|
||||||
|
if (atom == less) {
|
||||||
|
return -1;
|
||||||
|
} else if (atom == equal) {
|
||||||
|
return 0;
|
||||||
|
} else if (atom == greater) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
CompilerDirectives.transferToInterpreter();
|
||||||
|
var ordering = ctxRef.get().getBuiltins().ordering().ordering();
|
||||||
|
throw new PanicException(
|
||||||
|
ctxRef.get().getBuiltins().error().makeTypeError(ordering, result.getValue()), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.mutable;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
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.data.Array;
|
||||||
|
|
||||||
|
@BuiltinMethod(type = "Array", name = "copy", description = "Copies one array to another.")
|
||||||
|
public abstract class CopyNode extends Node {
|
||||||
|
|
||||||
|
static CopyNode build() {
|
||||||
|
return CopyNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Object execute(Array _this, long source_index, Array that, long dest_index, long count);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Object doArray(
|
||||||
|
Array _this,
|
||||||
|
long source_index,
|
||||||
|
Array that,
|
||||||
|
long dest_index,
|
||||||
|
long count,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
System.arraycopy(
|
||||||
|
_this.getItems(), (int) source_index, that.getItems(), (int) dest_index, (int) count);
|
||||||
|
return ctxRef.get().getBuiltins().nothing().newInstance();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.mutable;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.nodes.LoopNode;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
import org.enso.interpreter.runtime.state.data.EmptyMap;
|
||||||
|
|
||||||
|
@BuiltinMethod(type = "Array", name = "sort", description = "Sorts a mutable array in place.")
|
||||||
|
public abstract class SortNode extends Node {
|
||||||
|
private @Child ComparatorNode comparatorNode = ComparatorNode.build();
|
||||||
|
private final BranchProfile resultProfile = BranchProfile.create();
|
||||||
|
|
||||||
|
abstract Object execute(VirtualFrame frame, Object _this, Object comparator);
|
||||||
|
|
||||||
|
static SortNode build() {
|
||||||
|
return SortNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Object doSortFunction(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Array _this,
|
||||||
|
Function comparator,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
Comparator<Object> compare = getComparator(comparator, ctxRef);
|
||||||
|
return runSort(compare, _this, ctxRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Object doSortCallable(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Array _this,
|
||||||
|
Object comparator,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
Comparator<Object> compare = (l, r) -> comparatorNode.execute(frame, comparator, l, r);
|
||||||
|
return runSort(compare, _this, ctxRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Object doAtomThis(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Atom _this,
|
||||||
|
Object that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("ctxRef.get().getBuiltins().mutable().array()") AtomConstructor array) {
|
||||||
|
return ctxRef.get().getBuiltins().nothing().newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object runSort(Comparator<Object> compare, Array _this, ContextReference<Context> ctxRef) {
|
||||||
|
doSort(_this.getItems(), compare);
|
||||||
|
LoopNode.reportLoopCount(this, _this.length());
|
||||||
|
return ctxRef.get().getBuiltins().nothing().newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TruffleBoundary
|
||||||
|
void doSort(Object[] items, Comparator<Object> compare) {
|
||||||
|
Arrays.sort(items, compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SortComparator getComparator(Function comp, ContextReference<Context> ctxRef) {
|
||||||
|
return new SortComparator(comp, ctxRef, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SortComparator implements Comparator<Object> {
|
||||||
|
private final Function compFn;
|
||||||
|
private final ContextReference<Context> ctxRef;
|
||||||
|
private final Atom less;
|
||||||
|
private final Atom equal;
|
||||||
|
private final Atom greater;
|
||||||
|
private final SortNode outerThis;
|
||||||
|
|
||||||
|
SortComparator(Function compFn, ContextReference<Context> ctxRef, SortNode outerThis) {
|
||||||
|
this.compFn = compFn;
|
||||||
|
this.ctxRef = ctxRef;
|
||||||
|
this.less = ctxRef.get().getBuiltins().ordering().newLess();
|
||||||
|
this.equal = ctxRef.get().getBuiltins().ordering().newEqual();
|
||||||
|
this.greater = ctxRef.get().getBuiltins().ordering().newGreater();
|
||||||
|
this.outerThis = outerThis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Object o1, Object o2) {
|
||||||
|
Object[] args =
|
||||||
|
Function.ArgumentsHelper.buildArguments(
|
||||||
|
compFn, null, EmptyMap.create(), new Object[] {o1, o2});
|
||||||
|
Stateful result = (Stateful) (compFn).getCallTarget().call(args);
|
||||||
|
Object value = result.getValue();
|
||||||
|
return convertResult(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int convertResult(Object res) {
|
||||||
|
if (res == less) {
|
||||||
|
return -1;
|
||||||
|
} else if (res == equal) {
|
||||||
|
return 0;
|
||||||
|
} else if (res == greater) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
resultProfile.enter();
|
||||||
|
var ordering = ctxRef.get().getBuiltins().ordering().ordering();
|
||||||
|
throw new PanicException(
|
||||||
|
ctxRef.get().getBuiltins().error().makeTypeError(ordering, res), outerThis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
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.number.utils.BigIntegerOps;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.builtin.Ordering;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Big_Integer",
|
||||||
|
name = "compare_to",
|
||||||
|
description = "Comparison for big integers.")
|
||||||
|
public abstract class CompareToNode extends Node {
|
||||||
|
|
||||||
|
static CompareToNode build() {
|
||||||
|
return CompareToNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Atom execute(EnsoBigInteger _this, Object that);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doLong(
|
||||||
|
EnsoBigInteger _this,
|
||||||
|
long that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
return ordering.fromJava(BigIntegerOps.compareTo(_this.getValue(), that));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doBigInt(
|
||||||
|
EnsoBigInteger _this,
|
||||||
|
EnsoBigInteger that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
return ordering.fromJava(BigIntegerOps.compareTo(_this.getValue(), that.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doDecimal(
|
||||||
|
EnsoBigInteger _this,
|
||||||
|
double that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
return ordering.fromJava(BigIntegerOps.compareTo(_this.getValue(), that));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doOther(
|
||||||
|
EnsoBigInteger _this,
|
||||||
|
Object that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
CompilerDirectives.transferToInterpreter();
|
||||||
|
var number = ctxRef.get().getBuiltins().number().getNumber().newInstance();
|
||||||
|
var typeError = ctxRef.get().getBuiltins().error().makeTypeError(that, number);
|
||||||
|
throw new PanicException(typeError, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ordering getOrdering(ContextReference<Context> ctxRef) {
|
||||||
|
return ctxRef.get().getBuiltins().ordering();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
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.number.utils.BigIntegerOps;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.builtin.Ordering;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||||
|
|
||||||
|
@BuiltinMethod(type = "Decimal", name = "compare_to", description = "Comparison for decimals.")
|
||||||
|
public abstract class CompareToNode extends Node {
|
||||||
|
|
||||||
|
static CompareToNode build() {
|
||||||
|
return CompareToNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Atom execute(double _this, Object that);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doLong(
|
||||||
|
double _this,
|
||||||
|
long that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
if (_this == that) {
|
||||||
|
return ordering.newEqual();
|
||||||
|
} else if (_this > that) {
|
||||||
|
return ordering.newGreater();
|
||||||
|
} else {
|
||||||
|
return ordering.newLess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doBigInt(
|
||||||
|
double _this,
|
||||||
|
EnsoBigInteger that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
return ordering.fromJava(BigIntegerOps.compareTo(_this, that.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doDecimal(
|
||||||
|
double _this,
|
||||||
|
double that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
if (_this == that) {
|
||||||
|
return ordering.newEqual();
|
||||||
|
} else if (_this > that) {
|
||||||
|
return ordering.newGreater();
|
||||||
|
} else {
|
||||||
|
return ordering.newLess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doOther(
|
||||||
|
double _this, Object that, @CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
CompilerDirectives.transferToInterpreter();
|
||||||
|
var number = ctxRef.get().getBuiltins().number().getNumber().newInstance();
|
||||||
|
var typeError = ctxRef.get().getBuiltins().error().makeTypeError(that, number);
|
||||||
|
throw new PanicException(typeError, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ordering getOrdering(ContextReference<Context> ctxRef) {
|
||||||
|
return ctxRef.get().getBuiltins().ordering();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.number.smallInteger;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
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.number.utils.BigIntegerOps;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.builtin.Ordering;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Small_Integer",
|
||||||
|
name = "compare_to",
|
||||||
|
description = "Comparison for small integers.")
|
||||||
|
public abstract class CompareToNode extends Node {
|
||||||
|
|
||||||
|
static CompareToNode build() {
|
||||||
|
return CompareToNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Atom execute(long _this, Object that);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doLong(
|
||||||
|
long _this,
|
||||||
|
long that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
if (_this == that) {
|
||||||
|
return ordering.newEqual();
|
||||||
|
} else if (_this > that) {
|
||||||
|
return ordering.newGreater();
|
||||||
|
} else {
|
||||||
|
return ordering.newLess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doBigInt(
|
||||||
|
long _this,
|
||||||
|
EnsoBigInteger that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
return ordering.fromJava(BigIntegerOps.compareTo(_this, that.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doDecimal(
|
||||||
|
long _this,
|
||||||
|
double that,
|
||||||
|
@CachedContext(Language.class) ContextReference<Context> ctxRef,
|
||||||
|
@Cached("getOrdering(ctxRef)") Ordering ordering) {
|
||||||
|
if (_this == that) {
|
||||||
|
return ordering.newEqual();
|
||||||
|
} else if (_this > that) {
|
||||||
|
return ordering.newGreater();
|
||||||
|
} else {
|
||||||
|
return ordering.newLess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Atom doOther(
|
||||||
|
long _this, Object that, @CachedContext(Language.class) ContextReference<Context> ctxRef) {
|
||||||
|
CompilerDirectives.transferToInterpreter();
|
||||||
|
var number = ctxRef.get().getBuiltins().number().getNumber().newInstance();
|
||||||
|
var typeError = ctxRef.get().getBuiltins().error().makeTypeError(that, number);
|
||||||
|
throw new PanicException(typeError, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ordering getOrdering(ContextReference<Context> ctxRef) {
|
||||||
|
return ctxRef.get().getBuiltins().ordering();
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package org.enso.interpreter.node.expression.builtin.number.utils;
|
|||||||
import com.fasterxml.jackson.databind.node.BigIntegerNode;
|
import com.fasterxml.jackson.databind.node.BigIntegerNode;
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/** Re-exposes big-integer operations behind a truffle boundary. */
|
/** Re-exposes big-integer operations behind a truffle boundary. */
|
||||||
@ -204,6 +205,31 @@ public class BigIntegerOps {
|
|||||||
return BigIntegerOps.compare(a,BigInteger.ZERO) == 0;
|
return BigIntegerOps.compare(a,BigInteger.ZERO) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static int compareTo(long a, BigInteger b) {
|
||||||
|
return -b.signum();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static int compareTo(BigInteger a, long b) {
|
||||||
|
return a.signum();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static int compareTo(BigInteger a, BigInteger b) {
|
||||||
|
return a.compareTo(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static int compareTo(BigInteger a, double b) {
|
||||||
|
return (new BigDecimal(a)).compareTo(BigDecimal.valueOf(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static int compareTo(double a, BigInteger b) {
|
||||||
|
return BigDecimal.valueOf(a).compareTo(new BigDecimal(b));
|
||||||
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
public static boolean fitsInLong(BigInteger bigInteger) {
|
public static boolean fitsInLong(BigInteger bigInteger) {
|
||||||
return bigInteger.compareTo(MIN_LONG_BIGINT) >= 0 && bigInteger.compareTo(MAX_LONG_BIGINT) <= 0;
|
return bigInteger.compareTo(MIN_LONG_BIGINT) >= 0 && bigInteger.compareTo(MAX_LONG_BIGINT) <= 0;
|
||||||
|
@ -38,22 +38,24 @@ public class Builtins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Module module;
|
|
||||||
private final ModuleScope scope;
|
|
||||||
private final AtomConstructor nothing;
|
|
||||||
private final AtomConstructor any;
|
private final AtomConstructor any;
|
||||||
private final Number number;
|
|
||||||
private final AtomConstructor function;
|
|
||||||
private final AtomConstructor debug;
|
private final AtomConstructor debug;
|
||||||
private final AtomConstructor ensoProject;
|
private final AtomConstructor ensoProject;
|
||||||
private final Text text;
|
private final AtomConstructor function;
|
||||||
private final Error error;
|
private final AtomConstructor nothing;
|
||||||
|
|
||||||
private final Bool bool;
|
private final Bool bool;
|
||||||
private final System system;
|
private final Error error;
|
||||||
|
private final Meta meta;
|
||||||
|
private final Module module;
|
||||||
|
private final ModuleScope scope;
|
||||||
private final Mutable mutable;
|
private final Mutable mutable;
|
||||||
|
private final Number number;
|
||||||
|
private final Ordering ordering;
|
||||||
private final Polyglot polyglot;
|
private final Polyglot polyglot;
|
||||||
private final Resource resource;
|
private final Resource resource;
|
||||||
private final Meta meta;
|
private final System system;
|
||||||
|
private final Text text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance with builtin methods installed.
|
* Creates an instance with builtin methods installed.
|
||||||
@ -62,27 +64,28 @@ public class Builtins {
|
|||||||
*/
|
*/
|
||||||
public Builtins(Context context) {
|
public Builtins(Context context) {
|
||||||
Language language = context.getLanguage();
|
Language language = context.getLanguage();
|
||||||
|
|
||||||
module = Module.empty(QualifiedName.fromString(MODULE_NAME).get());
|
module = Module.empty(QualifiedName.fromString(MODULE_NAME).get());
|
||||||
scope = module.compileScope(context);
|
scope = module.compileScope(context);
|
||||||
nothing = new AtomConstructor("Nothing", scope).initializeFields();
|
|
||||||
any = new AtomConstructor("Any", scope).initializeFields();
|
any = new AtomConstructor("Any", scope).initializeFields();
|
||||||
bool = new Bool(language, scope);
|
bool = new Bool(language, scope);
|
||||||
error = new Error(language, scope);
|
|
||||||
mutable = new Mutable(language, scope);
|
|
||||||
function = new AtomConstructor("Function", scope).initializeFields();
|
|
||||||
text = new Text(language, scope);
|
|
||||||
debug = new AtomConstructor("Debug", scope).initializeFields();
|
debug = new AtomConstructor("Debug", scope).initializeFields();
|
||||||
ensoProject =
|
ensoProject =
|
||||||
new AtomConstructor("Enso_Project", scope)
|
new AtomConstructor("Enso_Project", scope)
|
||||||
.initializeFields(
|
.initializeFields(
|
||||||
new ArgumentDefinition(
|
new ArgumentDefinition(
|
||||||
0, "prim_root_file", ArgumentDefinition.ExecutionMode.EXECUTE));
|
0, "prim_root_file", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||||
system = new System(language, scope);
|
error = new Error(language, scope);
|
||||||
|
function = new AtomConstructor("Function", scope).initializeFields();
|
||||||
|
meta = new Meta(language, scope);
|
||||||
|
mutable = new Mutable(language, scope);
|
||||||
|
nothing = new AtomConstructor("Nothing", scope).initializeFields();
|
||||||
number = new Number(language, scope);
|
number = new Number(language, scope);
|
||||||
|
ordering = new Ordering(language, scope);
|
||||||
polyglot = new Polyglot(language, scope);
|
polyglot = new Polyglot(language, scope);
|
||||||
resource = new Resource(language, scope);
|
resource = new Resource(language, scope);
|
||||||
meta = new Meta(language, scope);
|
system = new System(language, scope);
|
||||||
|
text = new Text(language, scope);
|
||||||
|
|
||||||
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
||||||
AtomConstructor cons =
|
AtomConstructor cons =
|
||||||
@ -243,6 +246,11 @@ public class Builtins {
|
|||||||
return polyglot;
|
return polyglot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the container for ordering-related builtins */
|
||||||
|
public Ordering ordering() {
|
||||||
|
return ordering;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the builtin module scope.
|
* Returns the builtin module scope.
|
||||||
*
|
*
|
||||||
|
@ -11,6 +11,7 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
|
|||||||
/** Container for builtin Error types */
|
/** Container for builtin Error types */
|
||||||
public class Error {
|
public class Error {
|
||||||
private final AtomConstructor syntaxError;
|
private final AtomConstructor syntaxError;
|
||||||
|
private final AtomConstructor typeError;
|
||||||
private final AtomConstructor compileError;
|
private final AtomConstructor compileError;
|
||||||
private final AtomConstructor inexhaustivePatternMatchError;
|
private final AtomConstructor inexhaustivePatternMatchError;
|
||||||
private final AtomConstructor uninitializedState;
|
private final AtomConstructor uninitializedState;
|
||||||
@ -34,6 +35,11 @@ public class Error {
|
|||||||
new AtomConstructor("Syntax_Error", scope)
|
new AtomConstructor("Syntax_Error", scope)
|
||||||
.initializeFields(
|
.initializeFields(
|
||||||
new ArgumentDefinition(0, "message", ArgumentDefinition.ExecutionMode.EXECUTE));
|
new ArgumentDefinition(0, "message", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||||
|
typeError =
|
||||||
|
new AtomConstructor("Type_Error", scope)
|
||||||
|
.initializeFields(
|
||||||
|
new ArgumentDefinition(0, "expected", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||||
|
new ArgumentDefinition(0, "actual", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||||
compileError =
|
compileError =
|
||||||
new AtomConstructor("Compile_Error", scope)
|
new AtomConstructor("Compile_Error", scope)
|
||||||
.initializeFields(
|
.initializeFields(
|
||||||
@ -78,6 +84,9 @@ public class Error {
|
|||||||
return syntaxError;
|
return syntaxError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the builtin {@code Type_Error} atom constructor. */
|
||||||
|
public AtomConstructor typeError() { return typeError; }
|
||||||
|
|
||||||
/** @return the builtin {@code Compile_Error} atom constructor. */
|
/** @return the builtin {@code Compile_Error} atom constructor. */
|
||||||
public AtomConstructor compileError() {
|
public AtomConstructor compileError() {
|
||||||
return compileError;
|
return compileError;
|
||||||
@ -109,6 +118,17 @@ public class Error {
|
|||||||
return noSuchMethodError.newInstance(target, symbol);
|
return noSuchMethodError.newInstance(target, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the runtime representation of a {@code Type_Error}.
|
||||||
|
*
|
||||||
|
* @param expected the expected type
|
||||||
|
* @param actual the actual type
|
||||||
|
* @return a runtime representation of the error.
|
||||||
|
*/
|
||||||
|
public Atom makeTypeError(Object expected, Object actual) {
|
||||||
|
return typeError.newInstance(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the runtime representation of a {@code Polyglot_Error}.
|
* Creates an instance of the runtime representation of a {@code Polyglot_Error}.
|
||||||
*
|
*
|
||||||
|
@ -8,6 +8,7 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
|
|||||||
/** Container for builtin array-related types and functions. */
|
/** Container for builtin array-related types and functions. */
|
||||||
public class Mutable {
|
public class Mutable {
|
||||||
private final AtomConstructor array;
|
private final AtomConstructor array;
|
||||||
|
private final AtomConstructor ref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class, registering all relevant bindings in the provided scope.
|
* Creates a new instance of this class, registering all relevant bindings in the provided scope.
|
||||||
@ -28,8 +29,10 @@ public class Mutable {
|
|||||||
scope.registerMethod(array, "to_array", ToArrayMethodGen.makeFunction(language));
|
scope.registerMethod(array, "to_array", ToArrayMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(array, "at", GetAtMethodGen.makeFunction(language));
|
scope.registerMethod(array, "at", GetAtMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(array, "set_at", SetAtMethodGen.makeFunction(language));
|
scope.registerMethod(array, "set_at", SetAtMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(array, "copy", CopyMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(array, "sort", SortMethodGen.makeFunction(language));
|
||||||
|
|
||||||
AtomConstructor ref = new AtomConstructor("Ref", scope).initializeFields();
|
ref = new AtomConstructor("Ref", scope).initializeFields();
|
||||||
scope.registerConstructor(ref);
|
scope.registerConstructor(ref);
|
||||||
scope.registerMethod(ref, "new", NewRefMethodGen.makeFunction(language));
|
scope.registerMethod(ref, "new", NewRefMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(ref, "get", GetRefMethodGen.makeFunction(language));
|
scope.registerMethod(ref, "get", GetRefMethodGen.makeFunction(language));
|
||||||
@ -37,7 +40,12 @@ public class Mutable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return the Array constructor. */
|
/** @return the Array constructor. */
|
||||||
public AtomConstructor constructor() {
|
public AtomConstructor array() {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the Ref constructor. */
|
||||||
|
public AtomConstructor ref() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,11 @@ public class Number {
|
|||||||
"bit_shift_r",
|
"bit_shift_r",
|
||||||
org.enso.interpreter.node.expression.builtin.number.smallInteger.BitShiftRightMethodGen
|
org.enso.interpreter.node.expression.builtin.number.smallInteger.BitShiftRightMethodGen
|
||||||
.makeFunction(language));
|
.makeFunction(language));
|
||||||
|
scope.registerMethod(
|
||||||
|
smallInteger,
|
||||||
|
"compare_to",
|
||||||
|
org.enso.interpreter.node.expression.builtin.number.smallInteger.CompareToMethodGen
|
||||||
|
.makeFunction(language));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerBigIntegerMethods(Language language, ModuleScope scope) {
|
private void registerBigIntegerMethods(Language language, ModuleScope scope) {
|
||||||
@ -281,6 +286,11 @@ public class Number {
|
|||||||
"bit_shift_r",
|
"bit_shift_r",
|
||||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.BitShiftRightMethodGen
|
org.enso.interpreter.node.expression.builtin.number.bigInteger.BitShiftRightMethodGen
|
||||||
.makeFunction(language));
|
.makeFunction(language));
|
||||||
|
scope.registerMethod(
|
||||||
|
bigInteger,
|
||||||
|
"compare_to",
|
||||||
|
org.enso.interpreter.node.expression.builtin.number.bigInteger.CompareToMethodGen
|
||||||
|
.makeFunction(language));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerDecimalMethods(Language language, ModuleScope scope) {
|
private void registerDecimalMethods(Language language, ModuleScope scope) {
|
||||||
@ -360,6 +370,11 @@ public class Number {
|
|||||||
"ceil",
|
"ceil",
|
||||||
org.enso.interpreter.node.expression.builtin.number.decimal.CeilMethodGen.makeFunction(
|
org.enso.interpreter.node.expression.builtin.number.decimal.CeilMethodGen.makeFunction(
|
||||||
language));
|
language));
|
||||||
|
scope.registerMethod(
|
||||||
|
decimal,
|
||||||
|
"compare_to",
|
||||||
|
org.enso.interpreter.node.expression.builtin.number.decimal.CompareToMethodGen.makeFunction(
|
||||||
|
language));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the Int64 atom constructor. */
|
/** @return the Int64 atom constructor. */
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package org.enso.interpreter.runtime.builtin;
|
||||||
|
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
|
/** A container for builtin ordering types. */
|
||||||
|
public class Ordering {
|
||||||
|
private final AtomConstructor ordering;
|
||||||
|
private final AtomConstructor less;
|
||||||
|
private final AtomConstructor equal;
|
||||||
|
private final AtomConstructor greater;
|
||||||
|
|
||||||
|
public Ordering(Language language, ModuleScope scope) {
|
||||||
|
ordering = new AtomConstructor("Ordering", scope).initializeFields();
|
||||||
|
less = new AtomConstructor("Less", scope).initializeFields();
|
||||||
|
equal = new AtomConstructor("Equal", scope).initializeFields();
|
||||||
|
greater = new AtomConstructor("Greater", scope).initializeFields();
|
||||||
|
scope.registerConstructor(ordering);
|
||||||
|
scope.registerConstructor(less);
|
||||||
|
scope.registerConstructor(equal);
|
||||||
|
scope.registerConstructor(greater);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the java notion of ordering to the Enso notion of ordering.
|
||||||
|
*
|
||||||
|
* @param ord the java ordering
|
||||||
|
* @return the Enso ordering corresponding to {@code ord}
|
||||||
|
*/
|
||||||
|
public Atom fromJava(int ord) {
|
||||||
|
if (ord == 0) {
|
||||||
|
return newEqual();
|
||||||
|
} else if (ord > 0) {
|
||||||
|
return newGreater();
|
||||||
|
} else {
|
||||||
|
return newLess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a new instance of Less */
|
||||||
|
public Atom newLess() {
|
||||||
|
return less.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a new instance of Equal */
|
||||||
|
public Atom newEqual() {
|
||||||
|
return equal.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a new instance of Greater */
|
||||||
|
public Atom newGreater() {
|
||||||
|
return greater.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the Ordering constructor. */
|
||||||
|
public AtomConstructor ordering() {
|
||||||
|
return ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the Less constructor */
|
||||||
|
public AtomConstructor less() {
|
||||||
|
return less;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the Equal constructor */
|
||||||
|
public AtomConstructor equal() {
|
||||||
|
return equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the Greater constructor */
|
||||||
|
public AtomConstructor greater() {
|
||||||
|
return greater;
|
||||||
|
}
|
||||||
|
}
|
@ -59,10 +59,15 @@ public class Array implements TruffleObject {
|
|||||||
return items[(int) index];
|
return items[(int) index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the size of this array */
|
||||||
|
public int length() {
|
||||||
|
return this.items.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposes the size of this collection through the polyglot API.
|
* Exposes the size of this collection through the polyglot API.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the size of this array
|
||||||
*/
|
*/
|
||||||
@ExportMessage
|
@ExportMessage
|
||||||
long getArraySize() {
|
long getArraySize() {
|
||||||
|
@ -702,7 +702,7 @@ class IrToTruffle(
|
|||||||
|
|
||||||
runtimeConsOpt.map { atomCons =>
|
runtimeConsOpt.map { atomCons =>
|
||||||
val any = context.getBuiltins.any
|
val any = context.getBuiltins.any
|
||||||
val array = context.getBuiltins.mutable.constructor
|
val array = context.getBuiltins.mutable.array
|
||||||
val bool = context.getBuiltins.bool
|
val bool = context.getBuiltins.bool
|
||||||
val number = context.getBuiltins.number
|
val number = context.getBuiltins.number
|
||||||
val polyglot = context.getBuiltins.polyglot.getPolyglot
|
val polyglot = context.getBuiltins.polyglot.getPolyglot
|
||||||
|
@ -228,7 +228,7 @@ case object SuspendedArguments extends IRPass {
|
|||||||
case (arg, typ) =>
|
case (arg, typ) =>
|
||||||
arg match {
|
arg match {
|
||||||
case spec: IR.DefinitionArgument.Specified =>
|
case spec: IR.DefinitionArgument.Specified =>
|
||||||
if (representsSuspended(typ)) {
|
if (representsSuspended(typ) || spec.suspended) {
|
||||||
spec.copy(suspended = true)
|
spec.copy(suspended = true)
|
||||||
} else spec.copy(suspended = false)
|
} else spec.copy(suspended = false)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import java.time.format.DateTimeFormatterBuilder;
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
import java.time.temporal.TemporalAccessor;
|
import java.time.temporal.TemporalAccessor;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/** Utils for standard library operations on Time. */
|
/** Utils for standard library operations on Time. */
|
||||||
public class Time_Utils {
|
public class Time_Utils {
|
||||||
|
73
test/Benchmarks/src/Vector.enso
Normal file
73
test/Benchmarks/src/Vector.enso
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
from Base import all
|
||||||
|
|
||||||
|
import Test.Bench
|
||||||
|
|
||||||
|
polyglot java import java.util.Random
|
||||||
|
polyglot java import org.enso.base.Time_Utils
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Bench Utilities ============================================================
|
||||||
|
|
||||||
|
vector_size = 1000000
|
||||||
|
iter_size = 100
|
||||||
|
num_iterations = 10
|
||||||
|
|
||||||
|
make_sorted_ascending_vec : Integer -> Base.Vector.Vector
|
||||||
|
make_sorted_ascending_vec n = 0.up_to n+1 . to_vector
|
||||||
|
|
||||||
|
make_partially_sorted_vec : Integer -> Base.Vector.Vector
|
||||||
|
make_partially_sorted_vec n =
|
||||||
|
random_gen = Random.new [n].to_array
|
||||||
|
direction = Ref.new Sort_Order.Ascending
|
||||||
|
last_num = Ref.new 0
|
||||||
|
run_length = Ref.new 0
|
||||||
|
Base.Vector.fill n <|
|
||||||
|
case (Ref.get run_length) == 0 of
|
||||||
|
True ->
|
||||||
|
new_direction = if (random_gen.nextDouble []) > 0 then Sort_Order.Ascending else
|
||||||
|
Sort_Order.Descending
|
||||||
|
Ref.put direction new_direction
|
||||||
|
Ref.put run_length (((random_gen.nextLong []) % (n / 10).floor) - 1)
|
||||||
|
num = random_gen.nextInt []
|
||||||
|
Ref.put last_num num
|
||||||
|
num
|
||||||
|
False ->
|
||||||
|
change = ((random_gen.nextInt []).abs) % n
|
||||||
|
num = case Ref.get direction of
|
||||||
|
Sort_Order.Ascending ->
|
||||||
|
num = (Ref.get last_num) + change
|
||||||
|
Ref.put last_num num
|
||||||
|
num
|
||||||
|
Sort_Order.Descending ->
|
||||||
|
num = (Ref.get last_num) - change
|
||||||
|
Ref.put last_num num
|
||||||
|
num
|
||||||
|
Ref.put run_length ((Ref.get run_length) - 1)
|
||||||
|
num
|
||||||
|
|
||||||
|
make_random_vec : Integer -> Base.Vector.Vector
|
||||||
|
make_random_vec n =
|
||||||
|
random_gen = Random.new [n].to_array
|
||||||
|
Base.Vector.fill n (random_gen.nextLong [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# The Benchmarks ==============================================================
|
||||||
|
|
||||||
|
main =
|
||||||
|
sorted_vec = here.make_sorted_ascending_vec here.vector_size
|
||||||
|
partially_sorted_vec = here.make_partially_sorted_vec here.vector_size
|
||||||
|
random_vec = here.make_random_vec here.vector_size
|
||||||
|
projection = x -> x % 10
|
||||||
|
comparator = l -> r -> r.compare_to l
|
||||||
|
|
||||||
|
Bench.measure (sorted_vec.sort) "Already Sorted" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (sorted_vec.sort order=Sort_Order.Descending) "Sorted in Opposite Order" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (partially_sorted_vec.sort) "Sorted Runs Ascending" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (partially_sorted_vec.sort order=Sort_Order.Descending) "Sorted Runs Descending" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (random_vec.sort) "Random Elements Ascending" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (random_vec.sort order=Sort_Order.Descending) "Random Elements Descending" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (random_vec.sort on=projection) "Sorting with a Custom Projection" here.iter_size here.num_iterations
|
||||||
|
Bench.measure (random_vec.sort by=comparator) "Sorting with a Custom Comparison" here.iter_size here.num_iterations
|
||||||
|
|
@ -14,6 +14,6 @@ spec = describe "Noise" <|
|
|||||||
result-result . should_equal 0
|
result-result . should_equal 0
|
||||||
it "should allow the user to specify the interval" <|
|
it "should allow the user to specify the interval" <|
|
||||||
interval = Interval.inclusive -250 250
|
interval = Interval.inclusive -250 250
|
||||||
values = 1.up_to 10000 . to_vector . map (_.noise interval)
|
values = 1.up_to 10001 . to_vector . map (_.noise interval)
|
||||||
values.all (v -> (v >= -250) && (v <= 250)) . should_be_true
|
values.all (v -> (v >= -250) && (v <= 250)) . should_be_true
|
||||||
|
|
||||||
|
@ -2,6 +2,12 @@ from Base import all
|
|||||||
|
|
||||||
import Test
|
import Test
|
||||||
|
|
||||||
|
type Test a b
|
||||||
|
|
||||||
|
Test.== that = this.a == that.a
|
||||||
|
Test.compare_to that = if this == that then Ordering.Equal else
|
||||||
|
if this.a > that.a then Ordering.Greater else Ordering.Less
|
||||||
|
|
||||||
spec = describe "Vectors" <|
|
spec = describe "Vectors" <|
|
||||||
it "should allow vector creation with a programmatic constructor" <|
|
it "should allow vector creation with a programmatic constructor" <|
|
||||||
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
|
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
|
||||||
@ -115,9 +121,38 @@ spec = describe "Vectors" <|
|
|||||||
non_empty_vec.rest . should_equal [2, 3, 4, 5]
|
non_empty_vec.rest . should_equal [2, 3, 4, 5]
|
||||||
singleton_vec.rest . should_equal []
|
singleton_vec.rest . should_equal []
|
||||||
empty_vec.rest . should_equal Nothing
|
empty_vec.rest . should_equal Nothing
|
||||||
# it "should be able to be sorted" <|
|
it "should be able to be sorted" <|
|
||||||
# it "should have a stable sort" <|
|
empty_vec = []
|
||||||
# it "should be able to use a custom element projection" <|
|
short_vec = [2, 4, 38, -1, -1000, 3671, -32]
|
||||||
# it "should be able to use a custom comparator" <|
|
short_expected = [-1000, -32, -1, 2, 4, 38, 3671]
|
||||||
# it "should be able to sort in ascending and descending order" <|
|
empty_vec.sort . should_equal []
|
||||||
|
short_vec.sort . should_equal short_expected
|
||||||
|
it "should leave the original vector unchanged" <|
|
||||||
|
non_empty_vec = [2, 4, 2, 3, 2, 3]
|
||||||
|
sorted = non_empty_vec.sort
|
||||||
|
non_empty_vec . should_equal [2, 4, 2, 3, 2, 3]
|
||||||
|
sorted . should_equal [2, 2, 2, 3, 3, 4]
|
||||||
|
it "should have a stable sort" <|
|
||||||
|
small_vec = [Test 1 8, Test 1 3, Test -20 0, Test -1 1, Test -1 10, Test 4 0]
|
||||||
|
small_expected = [Test -20 0, Test -1 1, Test -1 10, Test 1 8, Test 1 3, Test 4 0]
|
||||||
|
small_vec.sort . should_equal small_expected
|
||||||
|
it "should be able to use a custom element projection" <|
|
||||||
|
small_vec = [Test 1 8, Test 1 3, Test -20 0, Test -1 1, Test -1 10, Test 4 0]
|
||||||
|
small_expected = [Test -20 0, Test 4 0, Test -1 1, Test 1 3, Test 1 8, Test -1 10]
|
||||||
|
small_vec.sort (on = _.b) . should_equal small_expected
|
||||||
|
it "should be able to use a custom comparator" <|
|
||||||
|
small_vec = [2, 7, -3, 383, -392, 28, -90]
|
||||||
|
small_expected = [383, 28, 7, 2, -3, -90, -392]
|
||||||
|
small_vec.sort (by = l -> r -> r.compare_to l) . should_equal small_expected
|
||||||
|
it "should be able to use a custom comparator and projection" <|
|
||||||
|
small_vec = [Test 1 8, Test 1 3, Test -20 0, Test -1 1, Test -1 10, Test 4 0]
|
||||||
|
small_expected = [Test -1 10, Test 1 8, Test 1 3, Test -1 1, Test -20 0, Test 4 0]
|
||||||
|
small_vec.sort (on = _.b) (by = l -> r -> r.compare_to l) . should_equal small_expected
|
||||||
|
it "should be able to sort in descending order" <|
|
||||||
|
small_vec = [2, 7, -3, 383, -392, 28, -90]
|
||||||
|
small_expected = [383, 28, 7, 2, -3, -90, -392]
|
||||||
|
small_vec.sort order=Sort_Order.Descending . should_equal small_expected
|
||||||
|
it "should be stable in descending order" <|
|
||||||
|
small_vec = [Test 1 8, Test 1 3, Test -20 0, Test -1 1, Test -1 10, Test 4 0]
|
||||||
|
small_expected = [Test 4 0, Test 1 3, Test 1 8, Test -1 10, Test -1 1, Test -20 0]
|
||||||
|
small_vec.sort order=Sort_Order.Descending . should_equal small_expected
|
||||||
|
Loading…
Reference in New Issue
Block a user