mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 13:15:52 +03:00
Runtime checking of ascribed expression types (#7796)
This commit is contained in:
parent
a5094225cf
commit
30a62b97bb
@ -947,6 +947,7 @@
|
||||
projects next to each other][7634]
|
||||
- [Support runtime checks of intersection types][7769]
|
||||
- [Merge `Small_Integer` and `Big_Integer` types][7636]
|
||||
- [Inline type ascriptions][7796]
|
||||
|
||||
[3227]: https://github.com/enso-org/enso/pull/3227
|
||||
[3248]: https://github.com/enso-org/enso/pull/3248
|
||||
@ -1086,6 +1087,7 @@
|
||||
[7634]: https://github.com/enso-org/enso/pull/7634
|
||||
[7769]: https://github.com/enso-org/enso/pull/7769
|
||||
[7636]: https://github.com/enso-org/enso/pull/7636
|
||||
[7796]: https://github.com/enso-org/enso/pull/7796
|
||||
|
||||
# Enso 2.0.0-alpha.18 (2021-10-12)
|
||||
|
||||
|
@ -87,7 +87,6 @@ working with types. These are listed below.
|
||||
| `;` | `< :`, `> =` | -2 | Left | Concatenates the left and right operand typesets to create a new typeset. |
|
||||
| `\|` | `> <:`, `> !`, `> in`, `> :` | 5 | Left | Computes the union of the left and right operand typesets. |
|
||||
| `&` | `> \|` | 6 | Left | Computes the intersection of the left and right operand typesets. |
|
||||
| `\` | `> &` | 7 | Left | Computes the subtraction of the right typeset from the left typeset. |
|
||||
| `:=` | `< :`, `> =`, `> ;` | -1 | Left | Creates a typeset member by assigning a value to a label. |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
@ -108,7 +107,6 @@ bind (`=`) has a relative level of -3 in this ordering.
|
||||
(declare-fun tsConcat () Int) ; `;`
|
||||
(declare-fun tsUnion () Int) ; `|`
|
||||
(declare-fun tsInter () Int) ; `&`
|
||||
(declare-fun minus () Int) ; `\`
|
||||
(declare-fun tsMember () Int) ; `:=`
|
||||
|
||||
(assert (> ascrip bind))
|
||||
@ -265,8 +263,6 @@ of typesets. Their syntax is as follows:
|
||||
arguments.
|
||||
- **Intersection - `&`:** The resultant typeset may contain values that are
|
||||
members of _both_ its arguments.
|
||||
- **Subtraction - `\`:** The resultant typeset may contain values that are in
|
||||
the first argument's set but not in the second.
|
||||
|
||||
> The actionables for this section are:
|
||||
>
|
||||
|
@ -194,10 +194,8 @@ They are as follows:
|
||||
product types.
|
||||
- **Union - `|`:** This operator creates a typeset that contains the members in
|
||||
the union of its operands.
|
||||
- **Intersection - `|`:** This operator creates a typeset that contains the
|
||||
- **Intersection - `&`:** This operator creates a typeset that contains the
|
||||
members in the intersection of its operands.
|
||||
- **Subtraction - `\`:** This operator creates a typeset that contains all of
|
||||
the members in the left operand that do not occur in the right operand.
|
||||
|
||||
For information on the syntactic usage of these operators, please see the
|
||||
section on [type operators](#../syntax/types.md#type-operators) in the syntax
|
||||
|
@ -99,7 +99,8 @@ public abstract class IndirectInvokeMethodNode extends Node {
|
||||
@Shared("indirectInvokeFunctionNode") @Cached IndirectInvokeFunctionNode invokeFunctionNode,
|
||||
@Cached ConditionProfile profile) {
|
||||
Function function =
|
||||
methodResolverNode.execute(EnsoContext.get(this).getBuiltins().dataflowError(), symbol);
|
||||
methodResolverNode.executeResolution(
|
||||
EnsoContext.get(this).getBuiltins().dataflowError(), symbol);
|
||||
if (profile.profile(function == null)) {
|
||||
return self;
|
||||
} else {
|
||||
|
@ -12,6 +12,7 @@ import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.control.TailCallException;
|
||||
import org.enso.interpreter.runtime.data.ArrayRope;
|
||||
import org.enso.interpreter.runtime.data.EnsoMultiValue;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
@ -152,6 +153,27 @@ public abstract class InvokeConversionNode extends BaseNode {
|
||||
throw that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doMultiValue(
|
||||
VirtualFrame frame,
|
||||
State state,
|
||||
UnresolvedConversion conversion,
|
||||
Object self,
|
||||
EnsoMultiValue that,
|
||||
Object[] arguments) {
|
||||
var type = extractType(self);
|
||||
var result = that.castTo(type);
|
||||
if (result == null) {
|
||||
throw new PanicException(
|
||||
EnsoContext.get(this)
|
||||
.getBuiltins()
|
||||
.error()
|
||||
.makeNoSuchConversion(type, self, conversion),
|
||||
this);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doWarning(
|
||||
VirtualFrame frame,
|
||||
|
@ -162,7 +162,7 @@ public abstract class InvokeMethodNode extends BaseNode {
|
||||
|
||||
Function resolveFunction(
|
||||
UnresolvedSymbol symbol, Type selfTpe, MethodResolverNode methodResolverNode) {
|
||||
Function function = methodResolverNode.execute(selfTpe, symbol);
|
||||
Function function = methodResolverNode.executeResolution(selfTpe, symbol);
|
||||
if (function == null) {
|
||||
return null;
|
||||
}
|
||||
@ -288,10 +288,11 @@ public abstract class InvokeMethodNode extends BaseNode {
|
||||
var fnAndType = self.resolveSymbol(methodResolverNode, symbol);
|
||||
if (fnAndType != null) {
|
||||
var unwrapSelf = self.castTo(fnAndType.getRight());
|
||||
assert unwrapSelf != null;
|
||||
assert arguments[0] == self;
|
||||
arguments[0] = unwrapSelf;
|
||||
return execute(frame, state, symbol, unwrapSelf, arguments);
|
||||
if (unwrapSelf != null) {
|
||||
assert arguments[0] == self;
|
||||
arguments[0] = unwrapSelf;
|
||||
}
|
||||
return invokeFunctionNode.execute(fnAndType.getLeft(), frame, state, arguments);
|
||||
}
|
||||
throw methodNotFound(symbol, self);
|
||||
}
|
||||
@ -305,7 +306,7 @@ public abstract class InvokeMethodNode extends BaseNode {
|
||||
Object[] arguments,
|
||||
@Shared("methodResolverNode") @Cached MethodResolverNode methodResolverNode) {
|
||||
Function function =
|
||||
methodResolverNode.execute(EnsoContext.get(this).getBuiltins().dataflowError(), symbol);
|
||||
methodResolverNode.executeResolution(EnsoContext.get(this).getBuiltins().dataflowError(), symbol);
|
||||
if (errorReceiverProfile.profile(function == null)) {
|
||||
return self;
|
||||
} else {
|
||||
@ -352,9 +353,10 @@ public abstract class InvokeMethodNode extends BaseNode {
|
||||
e);
|
||||
}
|
||||
|
||||
Type typeOfSymbol = symbol.resolveDeclaringType(this, types.getType(selfWithoutWarnings));
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
if (typeOfSymbol == builtins.any()) {
|
||||
var selfType = types.getType(selfWithoutWarnings);
|
||||
var fnAndType = symbol.resolveFor(this, selfType);
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
if (fnAndType != null && fnAndType.getRight() == builtins.any()) {
|
||||
return symbol
|
||||
.getScope()
|
||||
.lookupMethodDefinition(builtins.warning().getEigentype(), symbol.getName());
|
||||
|
@ -9,6 +9,7 @@ import org.enso.compiler.core.ir.Name;
|
||||
import org.enso.interpreter.EnsoLanguage;
|
||||
import org.enso.interpreter.node.BaseNode.TailStatus;
|
||||
import org.enso.interpreter.node.EnsoRootNode;
|
||||
import org.enso.interpreter.node.ExpressionNode;
|
||||
import org.enso.interpreter.node.callable.ApplicationNode;
|
||||
import org.enso.interpreter.node.callable.InvokeCallableNode.DefaultsExecutionMode;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
@ -55,6 +56,13 @@ public abstract class ReadArgumentCheckNode extends Node {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static ExpressionNode wrap(ExpressionNode original, ReadArgumentCheckNode check) {
|
||||
return new TypeCheckExpressionNode(original, check);
|
||||
}
|
||||
|
||||
/** Executes check or conversion of the value.abstract
|
||||
* @param frame frame requesting the conversion
|
||||
* @param value the value to convert
|
||||
@ -289,16 +297,28 @@ public abstract class ReadArgumentCheckNode extends Node {
|
||||
ApplicationNode findConversionNode(Type from) {
|
||||
var convAndType = findConversion(from);
|
||||
|
||||
if (convAndType != null && NodeUtil.findParent(this, ReadArgumentNode.class) instanceof ReadArgumentNode ran) {
|
||||
CompilerAsserts.neverPartOfCompilation();
|
||||
var convNode = LiteralNode.build(convAndType.getLeft());
|
||||
var intoNode = LiteralNode.build(convAndType.getRight());
|
||||
var valueNode = ran.plainRead();
|
||||
var args = new CallArgument[]{
|
||||
new CallArgument(null, intoNode),
|
||||
new CallArgument(null, valueNode)
|
||||
};
|
||||
return ApplicationNode.build(convNode, args, DefaultsExecutionMode.EXECUTE);
|
||||
if (convAndType != null) {
|
||||
if (NodeUtil.findParent(this, ReadArgumentNode.class) instanceof ReadArgumentNode ran) {
|
||||
CompilerAsserts.neverPartOfCompilation();
|
||||
var convNode = LiteralNode.build(convAndType.getLeft());
|
||||
var intoNode = LiteralNode.build(convAndType.getRight());
|
||||
var valueNode = ran.plainRead();
|
||||
var args = new CallArgument[]{
|
||||
new CallArgument(null, intoNode),
|
||||
new CallArgument(null, valueNode)
|
||||
};
|
||||
return ApplicationNode.build(convNode, args, DefaultsExecutionMode.EXECUTE);
|
||||
} else if (NodeUtil.findParent(this, TypeCheckExpressionNode.class) instanceof TypeCheckExpressionNode tcen) {
|
||||
CompilerAsserts.neverPartOfCompilation();
|
||||
var convNode = LiteralNode.build(convAndType.getLeft());
|
||||
var intoNode = LiteralNode.build(convAndType.getRight());
|
||||
var valueNode = tcen.original;
|
||||
var args = new CallArgument[]{
|
||||
new CallArgument(null, intoNode),
|
||||
new CallArgument(null, valueNode)
|
||||
};
|
||||
return ApplicationNode.build(convNode, args, DefaultsExecutionMode.EXECUTE);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -378,4 +398,29 @@ public abstract class ReadArgumentCheckNode extends Node {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TypeCheckExpressionNode extends ExpressionNode {
|
||||
@Child
|
||||
private ExpressionNode original;
|
||||
@Child
|
||||
private ReadArgumentCheckNode check;
|
||||
|
||||
TypeCheckExpressionNode(ExpressionNode original, ReadArgumentCheckNode check) {
|
||||
this.check = check;
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
var value = original.executeGeneric(frame);
|
||||
var result = check.handleCheckOrConversion(frame, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstrumentable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.graalvm.collections.Pair;
|
||||
|
||||
@GenerateUncached
|
||||
@ReportPolymorphism
|
||||
@ -22,15 +23,20 @@ public abstract class MethodResolverNode extends Node {
|
||||
return EnsoContext.get(this);
|
||||
}
|
||||
|
||||
public abstract Function execute(Type type, UnresolvedSymbol symbol);
|
||||
public abstract Pair<Function, Type> execute(Type type, UnresolvedSymbol symbol);
|
||||
|
||||
public Function expectNonNull(Object self, Type type, UnresolvedSymbol symbol) {
|
||||
public final Function executeResolution(Type type, UnresolvedSymbol symbol) {
|
||||
var pair = execute(type, symbol);
|
||||
return pair == null ? null : pair.getLeft();
|
||||
}
|
||||
|
||||
public final Function expectNonNull(Object self, Type type, UnresolvedSymbol symbol) {
|
||||
var result = execute(type, symbol);
|
||||
if (result == null) {
|
||||
throw new PanicException(
|
||||
EnsoContext.get(this).getBuiltins().error().makeNoSuchMethod(self, symbol), this);
|
||||
}
|
||||
return result;
|
||||
return result.getLeft();
|
||||
}
|
||||
|
||||
@Specialization(
|
||||
@ -40,17 +46,17 @@ public abstract class MethodResolverNode extends Node {
|
||||
"cachedType == type"
|
||||
},
|
||||
limit = "CACHE_SIZE")
|
||||
Function resolveCached(
|
||||
Pair<Function, Type> resolveCached(
|
||||
Type type,
|
||||
UnresolvedSymbol symbol,
|
||||
@Cached("symbol") UnresolvedSymbol cachedSymbol,
|
||||
@Cached("type") Type cachedType,
|
||||
@Cached("resolveUncached(cachedType, cachedSymbol)") Function function) {
|
||||
@Cached("resolveUncached(cachedType, cachedSymbol)") Pair<Function, Type> function) {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Specialization(replaces = "resolveCached")
|
||||
Function resolveUncached(Type self, UnresolvedSymbol symbol) {
|
||||
Pair<Function, Type> resolveUncached(Type self, UnresolvedSymbol symbol) {
|
||||
return symbol.resolveFor(this, self);
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.meta;
|
||||
|
||||
import com.ibm.icu.text.Normalizer;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.enso.interpreter.dsl.AcceptsError;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.data.EnsoMultiValue;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.error.WarningsLibrary;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
import org.enso.polyglot.common_utils.Core_Text_Utils;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Cached.Shared;
|
||||
import com.oracle.truffle.api.dsl.GenerateUncached;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import java.math.BigInteger;
|
||||
import org.enso.interpreter.dsl.AcceptsError;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.error.WarningsLibrary;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
import org.enso.polyglot.common_utils.Core_Text_Utils;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Any",
|
||||
@ -72,6 +75,18 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Specialization(guards="interop.isBoolean(other)")
|
||||
boolean equalsBoolInterop(
|
||||
boolean self, Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop
|
||||
) {
|
||||
try {
|
||||
return self == interop.asBoolean(other);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsLongLong(long self, long other) {
|
||||
return self == other;
|
||||
@ -92,6 +107,18 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Specialization(guards="interop.fitsInLong(other)")
|
||||
boolean equalsLongInterop(
|
||||
long self, Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop
|
||||
) {
|
||||
try {
|
||||
return self == interop.asLong(other);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsDoubleDouble(double self, double other) {
|
||||
if (Double.isNaN(self) || Double.isNaN(other)) {
|
||||
@ -117,6 +144,18 @@ public abstract class EqualsNode extends Node {
|
||||
return self == other.asDouble();
|
||||
}
|
||||
|
||||
@Specialization(guards="interop.fitsInDouble(other)")
|
||||
boolean equalsDoubleInterop(
|
||||
double self, Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop
|
||||
) {
|
||||
try {
|
||||
return self == interop.asDouble(other);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsDoubleText(double self, Text other) {
|
||||
return false;
|
||||
@ -154,6 +193,23 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
@Specialization(guards={
|
||||
"!isPrimitiveValue(other)",
|
||||
"interop.fitsInBigInteger(other)"
|
||||
})
|
||||
boolean equalsBigIntInterop(
|
||||
EnsoBigInteger self, Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop
|
||||
) {
|
||||
try {
|
||||
var otherBigInteger = InteropLibrary.getUncached().asBigInteger(other);
|
||||
return self.asBigInteger().equals(otherBigInteger);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsLongBigInt(long self, EnsoBigInteger other) {
|
||||
@ -236,6 +292,43 @@ public abstract class EqualsNode extends Node {
|
||||
return isSameObjectNode.execute(self, other) || equalsAtomNode.execute(self, other);
|
||||
}
|
||||
|
||||
|
||||
@Specialization
|
||||
boolean equalsReverseBoolean(
|
||||
TruffleObject self, boolean other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop,
|
||||
@Shared("reverse") @Cached EqualsNode reverse
|
||||
) {
|
||||
return reverse.execute(other, self);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsReverseLong(
|
||||
TruffleObject self, long other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop,
|
||||
@Shared("reverse") @Cached EqualsNode reverse
|
||||
) {
|
||||
return reverse.execute(other, self);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsReverseDouble(
|
||||
TruffleObject self, double other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop,
|
||||
@Shared("reverse") @Cached EqualsNode reverse
|
||||
) {
|
||||
return reverse.execute(other, self);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsReverseBigInt(
|
||||
TruffleObject self, EnsoBigInteger other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop,
|
||||
@Shared("reverse") @Cached EqualsNode reverse
|
||||
) {
|
||||
return reverse.execute(other, self);
|
||||
}
|
||||
|
||||
@Specialization(guards = "isNotPrimitive(self, other, interop, warnings)")
|
||||
boolean equalsComplex(
|
||||
Object self,
|
||||
@ -258,6 +351,9 @@ public abstract class EqualsNode extends Node {
|
||||
if (warnings.hasWarnings(a) || warnings.hasWarnings(b)) {
|
||||
return true;
|
||||
}
|
||||
if (a instanceof EnsoMultiValue || b instanceof EnsoMultiValue) {
|
||||
return true;
|
||||
}
|
||||
return !isPrimitive(a, interop) && !isPrimitive(b, interop);
|
||||
}
|
||||
|
||||
@ -269,11 +365,17 @@ public abstract class EqualsNode extends Node {
|
||||
* org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode}.
|
||||
*/
|
||||
static boolean isPrimitive(Object object, InteropLibrary interop) {
|
||||
return object instanceof Boolean
|
||||
|| object instanceof Long
|
||||
|| object instanceof Double
|
||||
return isPrimitiveValue(object)
|
||||
|| object instanceof EnsoBigInteger
|
||||
|| object instanceof Text
|
||||
|| interop.isString(object);
|
||||
|| interop.isString(object)
|
||||
|| interop.isNumber(object)
|
||||
|| interop.isBoolean(object);
|
||||
}
|
||||
|
||||
static boolean isPrimitiveValue(Object object) {
|
||||
return object instanceof Boolean
|
||||
|| object instanceof Long
|
||||
|| object instanceof Double;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ public abstract class GetAnnotationNode extends BaseNode {
|
||||
if (targetTypeResult instanceof Type targetType) {
|
||||
Function methodFunction;
|
||||
if (method instanceof UnresolvedSymbol symbol) {
|
||||
methodFunction = symbol.resolveFor(this, targetType);
|
||||
var pair = symbol.resolveFor(this, targetType);
|
||||
methodFunction = pair == null ? null : pair.getLeft();
|
||||
} else {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
var ctx = EnsoContext.get(this);
|
||||
|
@ -1,10 +1,9 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "abs", description = "Absolute value of a number.")
|
||||
public class AbsNode extends Node {
|
||||
public class AbsNode extends FloatNode {
|
||||
double execute(double self) {
|
||||
return Math.abs(self);
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "+", description = "Addition of numbers.")
|
||||
public abstract class AddNode extends Node {
|
||||
public abstract class AddNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static AddNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class AddNode extends Node {
|
||||
return self + BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached AddNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
@ -13,7 +12,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
type = "Decimal",
|
||||
name = "ceil",
|
||||
description = "Decimal ceiling, converting to a small or big integer depending on size.")
|
||||
public class CeilNode extends Node {
|
||||
public class CeilNode extends FloatNode {
|
||||
private final CountingConditionProfile fitsProfile = CountingConditionProfile.create();
|
||||
|
||||
Object execute(double self) {
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "/", description = "Division of numbers.")
|
||||
public abstract class DivideNode extends Node {
|
||||
public abstract class DivideNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class DivideNode extends Node {
|
||||
return self / BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached DivideNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
abstract class FloatNode extends Node {
|
||||
static final String INTEROP_LIMIT = "3";
|
||||
|
||||
final boolean isForeignNumber(InteropLibrary iop, TruffleObject obj) {
|
||||
if (obj instanceof EnsoBigInteger) {
|
||||
return false;
|
||||
}
|
||||
return iop.isNumber(obj);
|
||||
}
|
||||
|
||||
final Object handleInterop(
|
||||
boolean incomparableError,
|
||||
double self,
|
||||
TruffleObject that,
|
||||
InteropLibrary iop,
|
||||
ToEnsoNumberNode toEnsoNumberNode) {
|
||||
try {
|
||||
if (iop.fitsInLong(that)) {
|
||||
return iop.asLong(that);
|
||||
} else if (iop.fitsInDouble(that)) {
|
||||
return iop.asDouble(that);
|
||||
} else if (iop.fitsInBigInteger(that)) {
|
||||
return toEnsoNumberNode.execute(iop.asBigInteger(that));
|
||||
}
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
}
|
||||
return incomparableError ? incomparableError(self, that) : panicOtherwise(self, that);
|
||||
}
|
||||
|
||||
final PanicException panicOtherwise(double self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
}
|
||||
|
||||
final DataflowError incomparableError(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var incomparableErr = builtins.error().makeIncomparableValues(self, that);
|
||||
return DataflowError.withoutTrace(incomparableErr, this);
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
@ -13,7 +12,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
type = "Decimal",
|
||||
name = "floor",
|
||||
description = "Decimal floor, converting to a small or big integer depending on size.")
|
||||
public class FloorNode extends Node {
|
||||
public class FloorNode extends FloatNode {
|
||||
private final CountingConditionProfile fitsProfile = CountingConditionProfile.create();
|
||||
|
||||
Object execute(double self) {
|
||||
|
@ -1,16 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = ">", description = "Comparison of numbers.")
|
||||
public abstract class GreaterNode extends Node {
|
||||
public abstract class GreaterNode extends FloatNode {
|
||||
|
||||
abstract Object execute(double self, Object that);
|
||||
|
||||
@ -45,14 +47,18 @@ public abstract class GreaterNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached GreaterNode delegate) {
|
||||
return delegate.execute(self, handleInterop(true, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(double self, Object that) {
|
||||
return incomparableError(self, that);
|
||||
}
|
||||
|
||||
private DataflowError incomparableError(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var incomparableErr = builtins.error().makeIncomparableValues(self, that);
|
||||
return DataflowError.withoutTrace(incomparableErr, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = ">=", description = "Comparison of numbers.")
|
||||
public abstract class GreaterOrEqualNode extends Node {
|
||||
public abstract class GreaterOrEqualNode extends FloatNode {
|
||||
|
||||
abstract Object execute(double self, Object that);
|
||||
|
||||
@ -45,14 +47,18 @@ public abstract class GreaterOrEqualNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached GreaterOrEqualNode delegate) {
|
||||
return delegate.execute(self, handleInterop(true, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(double self, Object that) {
|
||||
return incomparableError(self, that);
|
||||
}
|
||||
|
||||
private DataflowError incomparableError(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var incomparableErr = builtins.error().makeIncomparableValues(self, that);
|
||||
return DataflowError.withoutTrace(incomparableErr, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "<", description = "Comparison of numbers.")
|
||||
public abstract class LessNode extends Node {
|
||||
public abstract class LessNode extends FloatNode {
|
||||
|
||||
abstract Object execute(double self, Object that);
|
||||
|
||||
@ -45,14 +47,18 @@ public abstract class LessNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached LessNode delegate) {
|
||||
return delegate.execute(self, handleInterop(true, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(double self, Object that) {
|
||||
return incomparableError(self, that);
|
||||
}
|
||||
|
||||
private DataflowError incomparableError(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var incomparableErr = builtins.error().makeIncomparableValues(self, that);
|
||||
return DataflowError.withoutTrace(incomparableErr, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "<=", description = "Comparison of numbers.")
|
||||
public abstract class LessOrEqualNode extends Node {
|
||||
public abstract class LessOrEqualNode extends FloatNode {
|
||||
|
||||
abstract Object execute(double self, Object that);
|
||||
|
||||
@ -45,14 +47,18 @@ public abstract class LessOrEqualNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached LessOrEqualNode delegate) {
|
||||
return delegate.execute(self, handleInterop(true, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(double self, Object that) {
|
||||
return incomparableError(self, that);
|
||||
}
|
||||
|
||||
private DataflowError incomparableError(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var incomparableErr = builtins.error().makeIncomparableValues(self, that);
|
||||
return DataflowError.withoutTrace(incomparableErr, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "%", description = "Modulo division of numbers.")
|
||||
public abstract class ModNode extends Node {
|
||||
public abstract class ModNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static ModNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class ModNode extends Node {
|
||||
return self % BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached ModNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "*", description = "Multiplication of numbers.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
public abstract class MultiplyNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static MultiplyNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class MultiplyNode extends Node {
|
||||
return self * BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached MultiplyNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "negate", description = "Negation for numbers.")
|
||||
public class NegateNode extends Node {
|
||||
public class NegateNode extends FloatNode {
|
||||
double execute(double self) {
|
||||
return -self;
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "^", description = "Exponentiation of numbers.")
|
||||
public abstract class PowNode extends Node {
|
||||
public abstract class PowNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static PowNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class PowNode extends Node {
|
||||
return Math.pow(self, BigIntegerOps.toDouble(that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached PowNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import com.oracle.truffle.api.profiles.PrimitiveValueProfile;
|
||||
@ -16,7 +15,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
type = "Decimal",
|
||||
name = "round",
|
||||
description = "Decimal ceiling, converting to a small or big integer depending on size.")
|
||||
public class RoundNode extends Node {
|
||||
public class RoundNode extends FloatNode {
|
||||
private final CountingConditionProfile fitsProfile = CountingConditionProfile.create();
|
||||
|
||||
private final PrimitiveValueProfile constantPlacesDecimalPlaces = PrimitiveValueProfile.create();
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "-", description = "Subtraction of numbers.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
public abstract class SubtractNode extends FloatNode {
|
||||
abstract double execute(double self, Object that);
|
||||
|
||||
static SubtractNode build() {
|
||||
@ -33,10 +34,18 @@ public abstract class SubtractNode extends Node {
|
||||
return self - BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
double doInterop(
|
||||
double self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = INTEROP_LIMIT) InteropLibrary iop,
|
||||
@Cached ToEnsoNumberNode toEnsoNumberNode,
|
||||
@Cached SubtractNode delegate) {
|
||||
return delegate.execute(self, handleInterop(false, self, that, iop, toEnsoNumberNode));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double self, Object that) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
var number = builtins.number().getNumber();
|
||||
throw new PanicException(builtins.error().makeTypeError(number, that, "that"), this);
|
||||
throw panicOtherwise(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "to_decimal", description = "Identity on decimals")
|
||||
public class ToDecimalNode extends Node {
|
||||
public class ToDecimalNode extends FloatNode {
|
||||
double execute(double self) {
|
||||
return self;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
@ -13,7 +12,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
type = "Decimal",
|
||||
name = "truncate_builtin",
|
||||
description = "Truncate a floating-point number to an integer by dropping the fractional part.")
|
||||
public class TruncateNode extends Node {
|
||||
public class TruncateNode extends FloatNode {
|
||||
private final CountingConditionProfile fitsProfile = CountingConditionProfile.create();
|
||||
|
||||
Object execute(double self) {
|
||||
|
@ -2,15 +2,12 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "abs", description = "Absolute value of a number")
|
||||
public abstract class AbsNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class AbsNode extends IntegerNode {
|
||||
|
||||
public static AbsNode build() {
|
||||
return AbsNodeGen.create();
|
||||
@ -39,6 +36,6 @@ public abstract class AbsNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "+", description = "Addition of numbers.")
|
||||
public abstract class AddNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class AddNode extends IntegerNode {
|
||||
|
||||
public abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -55,8 +56,17 @@ public abstract class AddNode extends Node {
|
||||
return self.asDouble() + that;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached AddNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "bit_and", description = "Bitwise and.")
|
||||
public abstract class BitAndNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class BitAndNode extends IntegerNode {
|
||||
|
||||
public abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -38,8 +39,17 @@ public abstract class BitAndNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.bitAnd(self.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached BitAndNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,11 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "bit_not", description = "Bitwise negation.")
|
||||
public abstract class BitNotNode extends Node {
|
||||
public abstract class BitNotNode extends IntegerNode {
|
||||
abstract Object execute(Object self);
|
||||
|
||||
static BitNotNode build() {
|
||||
@ -28,6 +27,6 @@ public abstract class BitNotNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "bit_or", description = "Bitwise or.")
|
||||
public abstract class BitOrNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class BitOrNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -38,8 +39,17 @@ public abstract class BitOrNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.bitOr(self.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached BitOrNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,20 @@ import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.ImportStatic;
|
||||
import com.oracle.truffle.api.dsl.NeverDefault;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@ImportStatic(BigIntegerOps.class)
|
||||
@BuiltinMethod(type = "Integer", name = "bit_shift", description = "Bitwise shift.")
|
||||
public abstract class BitShiftNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class BitShiftNode extends IntegerNode {
|
||||
|
||||
private final CountingConditionProfile canShiftLeftInLongProfile =
|
||||
CountingConditionProfile.create();
|
||||
private final CountingConditionProfile positiveFitsInInt = CountingConditionProfile.create();
|
||||
@ -124,9 +125,18 @@ public abstract class BitShiftNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached BitShiftNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
|
||||
boolean hasFreeBitsLeftShift(long number, long shift) {
|
||||
|
@ -4,13 +4,15 @@ import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Cached.Shared;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "bit_shift_r", description = "Bitwise right-shift.")
|
||||
public abstract class BitShiftRightNode extends Node {
|
||||
public abstract class BitShiftRightNode extends IntegerNode {
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
static BitShiftRightNode build() {
|
||||
@ -47,8 +49,17 @@ public abstract class BitShiftRightNode extends Node {
|
||||
return bitShiftNode.execute(self, new EnsoBigInteger(BigIntegerOps.negate(that.getValue())));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached BitShiftRightNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "bit_xor", description = "Bitwise exclusive or.")
|
||||
public abstract class BitXorNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class BitXorNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -38,8 +39,17 @@ public abstract class BitXorNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.bitXor(self.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached BitXorNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,11 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "ceil", description = "Small integer ceiling.")
|
||||
public abstract class CeilNode extends Node {
|
||||
public abstract class CeilNode extends IntegerNode {
|
||||
abstract Object execute(Object self);
|
||||
|
||||
public static CeilNode build() {
|
||||
@ -26,6 +25,6 @@ public abstract class CeilNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "div", description = "Division of numbers.")
|
||||
public abstract class DivNode extends Node {
|
||||
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class DivNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -53,8 +53,17 @@ public abstract class DivNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(self.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached DivNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,19 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "/", description = "Division of numbers.")
|
||||
public abstract class DivideNode extends Node {
|
||||
abstract double execute(Object self, Object that);
|
||||
public abstract class DivideNode extends IntegerNode {
|
||||
@Override
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
@ -45,8 +49,17 @@ public abstract class DivideNode extends Node {
|
||||
return BigIntegerOps.toDouble(self.getValue()) / that;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached DivideNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
Object doOther(Object self, Object that) {
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,11 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "floor", description = "Small integer floor.")
|
||||
public abstract class FloorNode extends Node {
|
||||
public abstract class FloorNode extends IntegerNode {
|
||||
|
||||
public abstract Object execute(Object self);
|
||||
|
||||
@ -27,6 +26,6 @@ public abstract class FloorNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -10,7 +13,7 @@ import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = ">", description = "Comparison of numbers.")
|
||||
public abstract class GreaterNode extends Node {
|
||||
public abstract class GreaterNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -48,6 +51,15 @@ public abstract class GreaterNode extends Node {
|
||||
return BigIntegerOps.compare(self.getValue(), that.getValue()) > 0;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached GreaterNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -10,7 +13,7 @@ import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = ">=", description = "Comparison of numbers.")
|
||||
public abstract class GreaterOrEqualNode extends Node {
|
||||
public abstract class GreaterOrEqualNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -48,6 +51,15 @@ public abstract class GreaterOrEqualNode extends Node {
|
||||
return BigIntegerOps.compare(self.getValue(), that.getValue()) >= 0;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached GreaterOrEqualNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
|
@ -0,0 +1,67 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
abstract class IntegerNode extends Node {
|
||||
@Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
|
||||
IntegerNode() {}
|
||||
|
||||
@TruffleBoundary
|
||||
final PanicException throwTypeErrorIfNotInt(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var intType = builtins.number().getInteger();
|
||||
var selfType = TypesLibrary.getUncached().getType(self);
|
||||
if (selfType != intType) {
|
||||
return new PanicException(builtins.error().makeTypeError(intType, self, "self"), this);
|
||||
} else {
|
||||
return new PanicException(builtins.error().makeTypeError(intType, that, "that"), this);
|
||||
}
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
final PanicException throwTypeErrorIfNotInt(Object self) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
var intType = builtins.number().getInteger();
|
||||
return new PanicException(builtins.error().makeTypeError(intType, self, "self"), this);
|
||||
}
|
||||
|
||||
final boolean isForeignNumber(InteropLibrary iop, TruffleObject obj) {
|
||||
if (obj instanceof EnsoBigInteger) {
|
||||
return false;
|
||||
}
|
||||
return iop.isNumber(obj);
|
||||
}
|
||||
|
||||
final Object doInterop(
|
||||
Object self, TruffleObject that, InteropLibrary iop, IntegerNode delegate) {
|
||||
try {
|
||||
if (iop.fitsInLong(that)) {
|
||||
return delegate.execute(self, iop.asLong(that));
|
||||
} else if (iop.fitsInDouble(that)) {
|
||||
return delegate.execute(self, iop.asDouble(that));
|
||||
} else if (iop.fitsInBigInteger(that)) {
|
||||
return delegate.execute(self, toEnsoNumberNode.execute(iop.asBigInteger(that)));
|
||||
}
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
}
|
||||
return doOther(self, that);
|
||||
}
|
||||
|
||||
Object execute(Object self, Object that) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
Object doOther(Object self, Object that) {
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||
|
||||
public final class IntegerUtils {
|
||||
private IntegerUtils() {}
|
||||
|
||||
@TruffleBoundary
|
||||
static PanicException throwTypeErrorIfNotInt(Object self, Object that, Node node) {
|
||||
var builtins = EnsoContext.get(node).getBuiltins();
|
||||
var intType = builtins.number().getInteger();
|
||||
var selfType = TypesLibrary.getUncached().getType(self);
|
||||
if (selfType != intType) {
|
||||
return new PanicException(builtins.error().makeTypeError(intType, self, "self"), node);
|
||||
} else {
|
||||
return new PanicException(builtins.error().makeTypeError(intType, that, "that"), node);
|
||||
}
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
static PanicException throwTypeErrorIfNotInt(Object self, Node node) {
|
||||
var builtins = EnsoContext.get(node).getBuiltins();
|
||||
var intType = builtins.number().getInteger();
|
||||
return new PanicException(builtins.error().makeTypeError(intType, self, "self"), node);
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -10,7 +13,7 @@ import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "<", description = "Comparison of numbers.")
|
||||
public abstract class LessNode extends Node {
|
||||
public abstract class LessNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -48,6 +51,15 @@ public abstract class LessNode extends Node {
|
||||
return BigIntegerOps.compare(self.getValue(), that.getValue()) < 0;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached LessNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
@ -10,8 +13,9 @@ import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "<=", description = "Comparison of numbers.")
|
||||
public abstract class LessOrEqualNode extends Node {
|
||||
public abstract class LessOrEqualNode extends IntegerNode {
|
||||
|
||||
@Override
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
static LessOrEqualNode build() {
|
||||
@ -48,6 +52,15 @@ public abstract class LessOrEqualNode extends Node {
|
||||
return BigIntegerOps.compare(self.getValue(), that.getValue()) <= 0;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached LessOrEqualNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
var builtins = EnsoContext.get(this).getBuiltins();
|
||||
|
@ -1,20 +1,21 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import java.math.BigInteger;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.error.DataflowError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "%", description = "Modulo division of numbers.")
|
||||
public abstract class ModNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class ModNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -78,8 +79,17 @@ public abstract class ModNode extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached ModNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "*", description = "Multiplication of numbers.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class MultiplyNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -53,8 +54,17 @@ public abstract class MultiplyNode extends Node {
|
||||
return BigIntegerOps.toDouble(self.getValue()) * that;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached MultiplyNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,12 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "negate", description = "Negation for numbers.")
|
||||
public abstract class NegateNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class NegateNode extends IntegerNode {
|
||||
|
||||
static NegateNode build() {
|
||||
return NegateNodeGen.create();
|
||||
@ -35,6 +32,6 @@ public abstract class NegateNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self, this);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.Node.Child;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import java.math.BigInteger;
|
||||
import org.enso.interpreter.dsl.*;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
@ -12,8 +12,8 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "parse", description = """
|
||||
Parse integer number""", autoRegister = false)
|
||||
public final class ParseIntegerNode extends Node {
|
||||
@Node.Child
|
||||
public final class ParseIntegerNode extends IntegerNode {
|
||||
@Child
|
||||
ToJavaStringNode toJavaString = ToJavaStringNode.build();
|
||||
private final BranchProfile noEx1 = BranchProfile.create();
|
||||
private final BranchProfile noEx2 = BranchProfile.create();
|
||||
|
@ -1,18 +1,21 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import com.oracle.truffle.api.nodes.Node.Child;
|
||||
import java.math.BigInteger;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "^", description = "Exponentiation of numbers.")
|
||||
public abstract class PowNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class PowNode extends IntegerNode {
|
||||
|
||||
private @Child MultiplyNode multiplyNode = MultiplyNode.build();
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
@ -86,8 +89,17 @@ public abstract class PowNode extends Node {
|
||||
return new EnsoBigInteger(BigInteger.valueOf(self));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached PowNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import com.oracle.truffle.api.profiles.CountingConditionProfile;
|
||||
import com.oracle.truffle.api.profiles.PrimitiveValueProfile;
|
||||
@ -11,7 +10,7 @@ import org.enso.interpreter.node.expression.builtin.number.utils.RoundHelpers;
|
||||
type = "Integer",
|
||||
name = "round",
|
||||
description = "Decimal ceiling, converting to a small or big integer depending on size.")
|
||||
public class RoundNode extends Node {
|
||||
public class RoundNode extends IntegerNode {
|
||||
private final CountingConditionProfile fitsProfile = CountingConditionProfile.create();
|
||||
|
||||
private final PrimitiveValueProfile constantPlacesDecimalPlaces = PrimitiveValueProfile.create();
|
||||
|
@ -1,16 +1,17 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.CachedLibrary;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Integer", name = "-", description = "Subtraction of numbers.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.create();
|
||||
public abstract class SubtractNode extends IntegerNode {
|
||||
|
||||
abstract Object execute(Object self, Object that);
|
||||
|
||||
@ -53,8 +54,17 @@ public abstract class SubtractNode extends Node {
|
||||
return BigIntegerOps.toDouble(self.getValue()) - that;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isForeignNumber(iop, that)")
|
||||
Object doInterop(
|
||||
Object self,
|
||||
TruffleObject that,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached SubtractNode delegate) {
|
||||
return super.doInterop(self, that, iop, delegate);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self, Object that) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, that, this);
|
||||
throw throwTypeErrorIfNotInt(self, that);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package org.enso.interpreter.node.expression.builtin.number.integer;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@ -11,7 +10,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
type = "Integer",
|
||||
name = "to_decimal",
|
||||
description = "Conversion of integers to decimals.")
|
||||
public abstract class ToDecimalNode extends Node {
|
||||
public abstract class ToDecimalNode extends IntegerNode {
|
||||
public abstract Object execute(Object self);
|
||||
|
||||
public static ToDecimalNode build() {
|
||||
@ -30,6 +29,6 @@ public abstract class ToDecimalNode extends Node {
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object self) {
|
||||
throw IntegerUtils.throwTypeErrorIfNotInt(self, this);
|
||||
throw throwTypeErrorIfNotInt(self);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.EnsoObject;
|
||||
import org.enso.interpreter.runtime.data.Type;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.graalvm.collections.Pair;
|
||||
|
||||
/** Simple runtime value representing a yet-unresolved by-name symbol. */
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
@ -56,32 +57,16 @@ public final class UnresolvedSymbol implements EnsoObject {
|
||||
* is returned. This is useful for certain subtyping relations, such as "any constructor is a
|
||||
* subtype of Any" or "Nat is a subtype of Int, is a subtype of Number".
|
||||
*
|
||||
* @param node the node that performs the query
|
||||
* @param type the type for which this symbol should be resolved
|
||||
* @return the resolved function definition, or null if not found
|
||||
* @return the resolved function definition and type it was resolved in, or null if not found
|
||||
*/
|
||||
public Function resolveFor(Node node, Type type) {
|
||||
for (var current : type.allTypes(EnsoContext.get(node))) {
|
||||
Function candidate = scope.lookupMethodDefinition(current, name);
|
||||
if (candidate != null) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the type where the symbol is declared.
|
||||
*
|
||||
* @param type the type for which this symbol should be resolved
|
||||
* @return the resolved function definition, or null if not found
|
||||
*/
|
||||
public Type resolveDeclaringType(Node node, Type type) {
|
||||
var ctx = EnsoContext.get(node);
|
||||
public Pair<Function, Type> resolveFor(Node node, Type type) {
|
||||
if (type != null) {
|
||||
for (var current : type.allTypes(ctx)) {
|
||||
for (var current : type.allTypes(EnsoContext.get(node))) {
|
||||
Function candidate = scope.lookupMethodDefinition(current, name);
|
||||
if (candidate != null) {
|
||||
return current;
|
||||
return Pair.create(candidate, current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,21 @@ package org.enso.interpreter.runtime.data;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Cached.Shared;
|
||||
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 java.math.BigInteger;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import org.enso.interpreter.node.callable.resolver.MethodResolverNode;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||
@ -16,6 +25,7 @@ import org.graalvm.collections.Pair;
|
||||
@ExportLibrary(TypesLibrary.class)
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public final class EnsoMultiValue implements EnsoObject {
|
||||
|
||||
@CompilationFinal(dimensions = 1)
|
||||
private final Type[] types;
|
||||
|
||||
@ -52,6 +62,289 @@ public final class EnsoMultiValue implements EnsoObject {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isBoolean(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isBoolean(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean asBoolean(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isBoolean(values[i])) {
|
||||
return iop.asBoolean(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isString(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isString(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
String asString(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (Object value : values) {
|
||||
if (iop.isString(value)) {
|
||||
return iop.asString(value);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isNumber(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isNumber(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInByte(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInByte(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInShort(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInShort(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInInt(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInShort(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInLong(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInLong(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInFloat(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInFloat(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInDouble(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInDouble(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
byte asByte(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInByte(values[i])) {
|
||||
return iop.asByte(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
short asShort(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInShort(values[i])) {
|
||||
return iop.asShort(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
int asInt(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInInt(values[i])) {
|
||||
return iop.asInt(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
long asLong(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInLong(values[i])) {
|
||||
return iop.asLong(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
float asFloat(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInFloat(values[i])) {
|
||||
return iop.asFloat(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
double asDouble(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInDouble(values[i])) {
|
||||
return iop.asDouble(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInBigInteger(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInBigInteger(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
BigInteger asBigInteger(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.fitsInBigInteger(values[i])) {
|
||||
return iop.asBigInteger(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isTime(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isTime(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
LocalTime asTime(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isTime(values[i])) {
|
||||
return iop.asTime(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isDate(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isDate(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
LocalDate asDate(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isDate(values[i])) {
|
||||
return iop.asDate(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isTimeZone(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isTimeZone(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
ZoneId asTimeZone(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isTimeZone(values[i])) {
|
||||
return iop.asTimeZone(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isDuration(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isDuration(values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Duration asDuration(@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop)
|
||||
throws UnsupportedMessageException {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (iop.isDuration(values[i])) {
|
||||
return iop.asDuration(values[i]);
|
||||
}
|
||||
}
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -82,12 +375,17 @@ public final class EnsoMultiValue implements EnsoObject {
|
||||
*/
|
||||
public final Pair<Function, Type> resolveSymbol(
|
||||
MethodResolverNode node, UnresolvedSymbol symbol) {
|
||||
var ctx = EnsoContext.get(node);
|
||||
Pair<Function, Type> foundAnyMethod = null;
|
||||
for (Type t : types) {
|
||||
var fn = node.execute(t, symbol);
|
||||
if (fn != null) {
|
||||
return Pair.create(fn, t);
|
||||
var fnAndType = node.execute(t, symbol);
|
||||
if (fnAndType != null) {
|
||||
if (fnAndType.getRight() != ctx.getBuiltins().any()) {
|
||||
return Pair.create(fnAndType.getLeft(), t);
|
||||
}
|
||||
foundAnyMethod = fnAndType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return foundAnyMethod;
|
||||
}
|
||||
}
|
||||
|
@ -680,43 +680,46 @@ class IrToTruffle(
|
||||
// === Utility Functions ====================================================
|
||||
// ==========================================================================
|
||||
|
||||
private def extractAscribedType(
|
||||
name: Name,
|
||||
t: Expression
|
||||
): ReadArgumentCheckNode = t match {
|
||||
case u: `type`.Set.Union =>
|
||||
ReadArgumentCheckNode.oneOf(
|
||||
name,
|
||||
u.operands.map(extractAscribedType(name, _)).asJava
|
||||
)
|
||||
case i: `type`.Set.Intersection =>
|
||||
ReadArgumentCheckNode.allOf(
|
||||
name,
|
||||
extractAscribedType(name, i.left),
|
||||
extractAscribedType(name, i.right)
|
||||
)
|
||||
case p: Application.Prefix => extractAscribedType(name, p.function)
|
||||
case _: Tpe.Function =>
|
||||
ReadArgumentCheckNode.build(
|
||||
name,
|
||||
context.getTopScope().getBuiltins().function()
|
||||
)
|
||||
case t => {
|
||||
t.getMetadata(TypeNames) match {
|
||||
case Some(
|
||||
BindingsMap
|
||||
.Resolution(BindingsMap.ResolvedType(mod, tpe))
|
||||
) =>
|
||||
ReadArgumentCheckNode.build(
|
||||
name,
|
||||
mod.unsafeAsModule().getScope.getTypes.get(tpe.name)
|
||||
)
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def checkRuntimeTypes(
|
||||
arg: DefinitionArgument
|
||||
): ReadArgumentCheckNode = {
|
||||
def extractAscribedType(t: Expression): ReadArgumentCheckNode = t match {
|
||||
case u: `type`.Set.Union =>
|
||||
ReadArgumentCheckNode.oneOf(
|
||||
arg.name,
|
||||
u.operands.map(extractAscribedType).asJava
|
||||
)
|
||||
case i: `type`.Set.Intersection =>
|
||||
ReadArgumentCheckNode.allOf(
|
||||
arg.name,
|
||||
extractAscribedType(i.left),
|
||||
extractAscribedType(i.right)
|
||||
)
|
||||
case p: Application.Prefix => extractAscribedType(p.function)
|
||||
case _: Tpe.Function =>
|
||||
ReadArgumentCheckNode.build(
|
||||
arg.name,
|
||||
context.getTopScope().getBuiltins().function()
|
||||
)
|
||||
case t => {
|
||||
t.getMetadata(TypeNames) match {
|
||||
case Some(
|
||||
BindingsMap
|
||||
.Resolution(BindingsMap.ResolvedType(mod, tpe))
|
||||
) =>
|
||||
ReadArgumentCheckNode.build(
|
||||
arg.name,
|
||||
mod.unsafeAsModule().getScope.getTypes.get(tpe.name)
|
||||
)
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg.ascribedType.map(extractAscribedType).getOrElse(null)
|
||||
arg.ascribedType.map(extractAscribedType(arg.name, _)).getOrElse(null)
|
||||
}
|
||||
|
||||
/** Checks if the expression has a @Builtin_Method annotation
|
||||
@ -984,7 +987,7 @@ class IrToTruffle(
|
||||
binding: Boolean,
|
||||
subjectToInstrumentation: Boolean
|
||||
): RuntimeExpression = {
|
||||
val runtimeExpression = ir match {
|
||||
var runtimeExpression = ir match {
|
||||
case block: Expression.Block => processBlock(block)
|
||||
case literal: Literal => processLiteral(literal)
|
||||
case app: Application =>
|
||||
@ -1009,8 +1012,20 @@ class IrToTruffle(
|
||||
s"Foreign expressions not yet implemented: $ir."
|
||||
)
|
||||
}
|
||||
|
||||
runtimeExpression.setTailStatus(getTailStatus(ir))
|
||||
|
||||
ir match {
|
||||
case _: Expression.Binding =>
|
||||
case _ =>
|
||||
val types = ir.getMetadata(TypeSignatures)
|
||||
types.foreach { tpe =>
|
||||
val checkNode = extractAscribedType(null, tpe.signature);
|
||||
if (checkNode != null) {
|
||||
runtimeExpression =
|
||||
ReadArgumentCheckNode.wrap(runtimeExpression, checkNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
runtimeExpression
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,16 @@ case object GatherDiagnostics extends IRPass {
|
||||
})
|
||||
.getOrElse(Nil)
|
||||
typeSignatureDiagnostics ++ x.diagnostics.toList
|
||||
case x => x.diagnostics.toList
|
||||
case x: Expression =>
|
||||
val typeSignatureDiagnostics =
|
||||
x.getMetadata(TypeSignatures)
|
||||
.map(_.signature.preorder.collect { case err: Diagnostic =>
|
||||
err
|
||||
})
|
||||
.getOrElse(Nil)
|
||||
typeSignatureDiagnostics ++ x.diagnostics.toList
|
||||
case x =>
|
||||
x.diagnostics.toList
|
||||
}.flatten
|
||||
DiagnosticsMeta(
|
||||
diagnostics.distinctBy(d => new DiagnosticKeys(d))
|
||||
|
@ -45,9 +45,14 @@ case object TypeNames extends IRPass {
|
||||
val bindingsMap =
|
||||
ir.unsafeGetMetadata(BindingAnalysis, "bindings analysis did not run")
|
||||
ir.copy(bindings = ir.bindings.map { d =>
|
||||
val mapped = d.mapExpressions(resolveExpression(bindingsMap, _))
|
||||
val typeParams = d match {
|
||||
case t: Definition.Type => t.params.map(_.name)
|
||||
case _ => Nil
|
||||
}
|
||||
val mapped =
|
||||
d.mapExpressions(resolveExpression(typeParams, bindingsMap, _))
|
||||
doResolveType(
|
||||
Nil,
|
||||
typeParams,
|
||||
bindingsMap,
|
||||
mapped match {
|
||||
case typ: Definition.Type =>
|
||||
@ -64,6 +69,7 @@ case object TypeNames extends IRPass {
|
||||
}
|
||||
|
||||
private def resolveExpression(
|
||||
typeParams: List[Name],
|
||||
bindingsMap: BindingsMap,
|
||||
ir: Expression
|
||||
): Expression = {
|
||||
@ -71,11 +77,11 @@ case object TypeNames extends IRPass {
|
||||
val processedIr = ir match {
|
||||
case fn: Function.Lambda =>
|
||||
fn.copy(arguments =
|
||||
fn.arguments.map(doResolveType(Nil, bindingsMap, _))
|
||||
fn.arguments.map(doResolveType(typeParams, bindingsMap, _))
|
||||
)
|
||||
case x => x
|
||||
}
|
||||
doResolveType(Nil, bindingsMap, processedIr.mapExpressions(go))
|
||||
doResolveType(typeParams, bindingsMap, processedIr.mapExpressions(go))
|
||||
}
|
||||
go(ir)
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
package org.enso.interpreter.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.enso.polyglot.MethodNames;
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.PolyglotException;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class BinaryOpFloatTest extends TestBase {
|
||||
private static final String[] OPERATIONS = {
|
||||
" +", " -", " ^", " *", " %", " <=", " <", " >=", " >", " /"
|
||||
};
|
||||
|
||||
@Parameterized.Parameters(name="({1}){0} ({2})")
|
||||
public static Object[][] parameters() {
|
||||
var r = new Random();
|
||||
var randomOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextDouble(), switch (op) {
|
||||
case " ^" -> r.nextDouble(10);
|
||||
case " *" -> r.nextDouble(Integer.MAX_VALUE);
|
||||
default -> r.nextDouble();
|
||||
}}
|
||||
);
|
||||
var zeroOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextDouble(), 0.0 }
|
||||
);
|
||||
var oneOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextDouble(), 1.0 }
|
||||
);
|
||||
var extraOps = Stream.of(
|
||||
new Object[] { " %", 19.73, 12.10 },
|
||||
new Object[] { " ^", 10.12, 73.19 }
|
||||
);
|
||||
return Streams.concat(
|
||||
randomOps,
|
||||
zeroOps,
|
||||
oneOps,
|
||||
extraOps
|
||||
).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
private static Context ctx;
|
||||
@BeforeClass
|
||||
public static void initContext() {
|
||||
ctx = createDefaultContext();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void closeContext() {
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
|
||||
private final String operation;
|
||||
private final double n1;
|
||||
private final double n2;
|
||||
|
||||
public BinaryOpFloatTest(String operation, double n1, double n2) {
|
||||
this.operation = operation;
|
||||
this.n1 = n1;
|
||||
this.n2 = n2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyOperationOnForeignObject() {
|
||||
executeInContext(ctx, () -> {
|
||||
var code = """
|
||||
fn a b = a{op} b
|
||||
""".replace("{op}", operation);
|
||||
var fn = ctx.eval("enso", code).invokeMember(MethodNames.Module.EVAL_EXPRESSION, "fn");
|
||||
|
||||
var r1 = execute(fn, n1, n2);
|
||||
|
||||
var wrap2 = ctx.asValue(new WrappedPrimitive(n2));
|
||||
var r2 = execute(fn, n1, wrap2);
|
||||
|
||||
assertSameResult(r1, r2);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private Value execute(Value fn, Object... args) {
|
||||
try {
|
||||
return fn.execute(args);
|
||||
} catch (PolyglotException ex) {
|
||||
return ex.getGuestObject();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSameResult(Value r1, Value r2) {
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.isException(), r2.isException());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.isBoolean(), r2.isBoolean());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInLong(), r2.fitsInLong());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInDouble(), r2.fitsInDouble());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInBigInteger(), r2.fitsInBigInteger());
|
||||
|
||||
if (r1.fitsInLong()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asLong(), r2.asLong());
|
||||
} else if (r1.fitsInDouble()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asDouble(), r2.asDouble(), 0.1);
|
||||
} else if (r1.fitsInBigInteger()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asBigInteger(), r2.asBigInteger());
|
||||
} else if (r1.isBoolean()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asBoolean(), r2.asBoolean());
|
||||
} else if (r1.isException()) {
|
||||
assertTrue("Both are exceptions for " + n1 + operation + " " + n2, r2.isException());
|
||||
} else {
|
||||
fail("Doesn't fit: " + r1);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package org.enso.interpreter.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.enso.polyglot.MethodNames;
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class BinaryOpIntegerTest extends TestBase {
|
||||
private static final String[] OPERATIONS = {
|
||||
" +", " -", " ^", " *", " %", " <=", " <", " >=", " >", " /",
|
||||
".div", ".bit_xor", ".bit_shift", ".bit_shift_r", ".bit_or", ".bit_and"
|
||||
};
|
||||
|
||||
@Parameterized.Parameters(name="({1}){0} ({2})")
|
||||
public static Object[][] parameters() {
|
||||
var r = new Random();
|
||||
var randomOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextLong(), switch (op) {
|
||||
case " ^" -> r.nextLong(10);
|
||||
case " *" -> r.nextLong(Integer.MAX_VALUE);
|
||||
default -> r.nextLong();
|
||||
}}
|
||||
);
|
||||
var zeroOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextLong(), 0 }
|
||||
);
|
||||
var oneOps = Arrays.asList(OPERATIONS).stream().map(
|
||||
(op) -> new Object[] { op, r.nextLong(), 1 }
|
||||
);
|
||||
var extraOps = Stream.of(
|
||||
new Object[] { " %", 19, 73 },
|
||||
new Object[] { ".bit_shift", 12, 10 }
|
||||
);
|
||||
return Streams.concat(
|
||||
randomOps,
|
||||
zeroOps,
|
||||
oneOps,
|
||||
extraOps
|
||||
).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
private static Context ctx;
|
||||
@BeforeClass
|
||||
public static void initContext() {
|
||||
ctx = createDefaultContext();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void closeContext() {
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
|
||||
private final String operation;
|
||||
private final long n1;
|
||||
private final long n2;
|
||||
|
||||
public BinaryOpIntegerTest(String operation, long n1, long n2) {
|
||||
this.operation = operation;
|
||||
this.n1 = n1;
|
||||
this.n2 = n2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyOperationOnForeignObject() {
|
||||
executeInContext(ctx, () -> {
|
||||
var code = """
|
||||
fn a b = a{op} b
|
||||
""".replace("{op}", operation);
|
||||
var fn = ctx.eval("enso", code).invokeMember(MethodNames.Module.EVAL_EXPRESSION, "fn");
|
||||
|
||||
var r1 = fn.execute(n1, n2);
|
||||
|
||||
var wrap2 = ctx.asValue(new WrappedPrimitive(n2));
|
||||
var r2 = fn.execute(n1, wrap2);
|
||||
|
||||
assertSameResult(r1, r2);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void assertSameResult(Value r1, Value r2) {
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.isException(), r2.isException());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.isBoolean(), r2.isBoolean());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInLong(), r2.fitsInLong());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInDouble(), r2.fitsInDouble());
|
||||
assertEquals("r1: " + r1 + " r2: " + r2, r1.fitsInBigInteger(), r2.fitsInBigInteger());
|
||||
|
||||
if (r1.fitsInLong()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asLong(), r2.asLong());
|
||||
} else if (r1.fitsInDouble()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asDouble(), r2.asDouble(), 0.1);
|
||||
} else if (r1.fitsInBigInteger()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asBigInteger(), r2.asBigInteger());
|
||||
} else if (r1.isBoolean()) {
|
||||
assertEquals("Results for " + n1 + operation + " " + n2, r1.asBoolean(), r2.asBoolean());
|
||||
} else if (r1.isException()) {
|
||||
assertTrue("Both are exceptions for " + n1 + operation + " " + n2, r2.isException());
|
||||
} else {
|
||||
fail("Doesn't fit: " + r1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +1,5 @@
|
||||
package org.enso.interpreter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.oracle.truffle.api.debug.DebugException;
|
||||
import com.oracle.truffle.api.debug.DebugScope;
|
||||
import com.oracle.truffle.api.debug.DebugStackFrame;
|
||||
import com.oracle.truffle.api.debug.DebugValue;
|
||||
import com.oracle.truffle.api.debug.Debugger;
|
||||
import com.oracle.truffle.api.debug.DebuggerSession;
|
||||
import com.oracle.truffle.api.debug.SuspendedCallback;
|
||||
import com.oracle.truffle.api.debug.SuspendedEvent;
|
||||
import com.oracle.truffle.api.nodes.LanguageInfo;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
@ -29,6 +14,7 @@ import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.enso.polyglot.MethodNames.Module;
|
||||
import org.enso.polyglot.RuntimeOptions;
|
||||
import org.graalvm.polyglot.Context;
|
||||
@ -39,9 +25,24 @@ import org.graalvm.polyglot.Value;
|
||||
import org.graalvm.polyglot.io.IOAccess;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.oracle.truffle.api.debug.DebugException;
|
||||
import com.oracle.truffle.api.debug.DebugScope;
|
||||
import com.oracle.truffle.api.debug.DebugStackFrame;
|
||||
import com.oracle.truffle.api.debug.DebugValue;
|
||||
import com.oracle.truffle.api.debug.Debugger;
|
||||
import com.oracle.truffle.api.debug.DebuggerSession;
|
||||
import com.oracle.truffle.api.debug.SuspendedCallback;
|
||||
import com.oracle.truffle.api.debug.SuspendedEvent;
|
||||
import com.oracle.truffle.api.nodes.LanguageInfo;
|
||||
|
||||
public class DebuggingEnsoTest {
|
||||
private Context context;
|
||||
private Engine engine;
|
||||
@ -107,6 +108,8 @@ public class DebuggingEnsoTest {
|
||||
}
|
||||
|
||||
private Value createEnsoMethod(String source, String methodName) {
|
||||
Value m = context.eval(createEnsoSource("from Standard.Base import all\n\n" + methodName + " = 10"));
|
||||
m.invokeMember(Module.EVAL_EXPRESSION, methodName);
|
||||
Value module = context.eval(createEnsoSource(source));
|
||||
return module.invokeMember(Module.EVAL_EXPRESSION, methodName);
|
||||
}
|
||||
@ -118,8 +121,8 @@ public class DebuggingEnsoTest {
|
||||
@Test
|
||||
public void recursiveFactorialCall() {
|
||||
final Value facFn = createEnsoMethod("""
|
||||
from Standard.Base.Data.Ordering import all
|
||||
|
||||
from Standard.Base import all
|
||||
|
||||
fac : Number -> Number
|
||||
fac n =
|
||||
facacc : Number -> Number -> Number
|
||||
@ -156,7 +159,7 @@ public class DebuggingEnsoTest {
|
||||
bar arg_bar =
|
||||
loc_bar = arg_bar + 1
|
||||
loc_bar
|
||||
|
||||
|
||||
foo x =
|
||||
loc_foo = 1
|
||||
bar loc_foo
|
||||
@ -195,7 +198,7 @@ public class DebuggingEnsoTest {
|
||||
Value fooFunc = createEnsoMethod("""
|
||||
polyglot java import java.nio.file.Path
|
||||
polyglot java import java.util.ArrayList
|
||||
|
||||
|
||||
foo x =
|
||||
path = Path.of 'blaaaaa'
|
||||
list = ArrayList.new
|
||||
@ -231,7 +234,7 @@ public class DebuggingEnsoTest {
|
||||
public void testHostValueAsAtomField() {
|
||||
Value fooFunc = createEnsoMethod("""
|
||||
from Standard.Base import Vector
|
||||
|
||||
|
||||
foo x =
|
||||
vec_builder = Vector.new_builder
|
||||
end = 42
|
||||
@ -256,7 +259,7 @@ public class DebuggingEnsoTest {
|
||||
public void testEvaluateExpression() {
|
||||
Value fooFunc = createEnsoMethod("""
|
||||
polyglot java import java.nio.file.Path
|
||||
|
||||
|
||||
foo x =
|
||||
a = 10
|
||||
b = 20
|
||||
@ -323,7 +326,7 @@ public class DebuggingEnsoTest {
|
||||
Value fooFunc = createEnsoMethod("""
|
||||
bar =
|
||||
loc_bar = 42
|
||||
|
||||
|
||||
foo x =
|
||||
a = 10 # Will get modified to 1
|
||||
b = 20 # Will get modified to 2
|
||||
@ -480,10 +483,10 @@ public class DebuggingEnsoTest {
|
||||
public void testSteppingOverUseStdLib() {
|
||||
Source src = createEnsoSource("""
|
||||
from Standard.Base import Vector
|
||||
|
||||
|
||||
bar vec num_elems =
|
||||
vec.slice 0 num_elems
|
||||
|
||||
|
||||
foo x =
|
||||
vec_builder = Vector.new_builder
|
||||
vec_builder.append 1
|
||||
|
@ -3,6 +3,13 @@ package org.enso.interpreter.test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
@ -10,9 +17,11 @@ import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.EqualsNode;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.EqualsNodeGen;
|
||||
import org.enso.polyglot.MethodNames;
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.junit.AfterClass;
|
||||
@ -189,4 +198,91 @@ public class EqualsTest extends TestBase {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleNumberLong() {
|
||||
var ensoNumber = unwrapValue(context, createValue(context, "1", ""));
|
||||
var foreignNumber = new WrappedPrimitive(1);
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(ensoNumber, foreignNumber.asDirect()));
|
||||
assertTrue(equalsNode.execute(ensoNumber, foreignNumber));
|
||||
assertTrue(equalsNode.execute(foreignNumber, ensoNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleNumberDouble() {
|
||||
var ensoNumber = unwrapValue(context, createValue(context, "1.0", ""));
|
||||
var foreignNumber = new WrappedPrimitive(1.0);
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(ensoNumber, foreignNumber.asDirect()));
|
||||
assertTrue(equalsNode.execute(ensoNumber, foreignNumber));
|
||||
assertTrue(equalsNode.execute(foreignNumber, ensoNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleNumberBigInt() {
|
||||
var value = new BigInteger("43207431473298432194374819743291479009431478329");
|
||||
var ensoNumber = unwrapValue(context, createValue(context, value.toString(), ""));
|
||||
var foreignNumber = new WrappedPrimitive(value);
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(ensoNumber, foreignNumber));
|
||||
assertTrue(equalsNode.execute(foreignNumber, ensoNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleBoolean() {
|
||||
var ensoBoolean =
|
||||
unwrapValue(context, createValue(context, "True", "from Standard.Base import True"));
|
||||
var foreignBoolean = new WrappedPrimitive(true);
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(ensoBoolean, foreignBoolean.asDirect()));
|
||||
assertTrue(equalsNode.execute(ensoBoolean, foreignBoolean));
|
||||
assertTrue(equalsNode.execute(foreignBoolean, ensoBoolean));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleString() {
|
||||
var ensoText = unwrapValue(context, createValue(context, "'Hello'", ""));
|
||||
var foreignString = new WrappedPrimitive("Hello");
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(ensoText, foreignString.asDirect()));
|
||||
assertTrue(equalsNode.execute(ensoText, foreignString));
|
||||
assertTrue(equalsNode.execute(foreignString, ensoText));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruffleNumberPlus() {
|
||||
var plus100 = context.eval("enso", """
|
||||
plus100 x = 100+x
|
||||
""").invokeMember(MethodNames.Module.EVAL_EXPRESSION, "plus100");
|
||||
assertTrue("plus100 can be executed", plus100.canExecute());
|
||||
var foreignNumber = context.asValue(new WrappedPrimitive(42));
|
||||
var hundred42 = unwrapValue(context, plus100.execute(foreignNumber));
|
||||
executeInContext(context,
|
||||
() -> {
|
||||
assertTrue(equalsNode.execute(142L, hundred42));
|
||||
assertTrue(equalsNode.execute(hundred42, 142L));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,42 @@ public class SignatureTest extends TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongLiteralSignature() throws Exception {
|
||||
final URI uri = new URI("memory://literal_signature.enso");
|
||||
final Source src = Source.newBuilder("enso", """
|
||||
neg a = 0 - a:Xyz
|
||||
""",uri.getAuthority())
|
||||
.uri(uri)
|
||||
.buildLiteral();
|
||||
|
||||
try {
|
||||
var module = ctx.eval(src);
|
||||
var neg = module.invokeMember("eval_expression", "neg").execute(-1);
|
||||
fail("Expecting an exception from compilation, not: " + neg);
|
||||
} catch (PolyglotException e) {
|
||||
assertTrue("It is a syntax error exception", e.isSyntaxError());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongExpressionSignature() throws Exception {
|
||||
final URI uri = new URI("memory://exp_signature.enso");
|
||||
final Source src = Source.newBuilder("enso", """
|
||||
neg a = (0 - a):Xyz
|
||||
""",uri.getAuthority())
|
||||
.uri(uri)
|
||||
.buildLiteral();
|
||||
|
||||
try {
|
||||
var module = ctx.eval(src);
|
||||
var neg = module.invokeMember("eval_expression", "neg").execute(-1);
|
||||
fail("Expecting an exception from compilation, not: " + neg);
|
||||
} catch (PolyglotException e) {
|
||||
assertTrue("It is a syntax error exception", e.isSyntaxError());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongAscribedTypeSignature() throws Exception {
|
||||
final URI uri = new URI("memory://neg.enso");
|
||||
@ -621,10 +657,9 @@ public class SignatureTest extends TestBase {
|
||||
self.dict.mul self.value that.value
|
||||
|
||||
compute (a : Plus & Mul) (b : Plus & Mul) =
|
||||
add (x:Plus) (y:Plus) = x+y
|
||||
p = add a b
|
||||
p = a+b
|
||||
m = a*b
|
||||
add p m
|
||||
p:Plus + m:Plus
|
||||
|
||||
type BooleanPlus
|
||||
plus a:Boolean b:Boolean = a || b
|
||||
|
@ -0,0 +1,145 @@
|
||||
package org.enso.interpreter.test;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import java.math.BigInteger;
|
||||
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
final class WrappedPrimitive implements TruffleObject {
|
||||
|
||||
private final Object value;
|
||||
|
||||
WrappedPrimitive(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
WrappedPrimitive(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
WrappedPrimitive(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
WrappedPrimitive(BigInteger value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
WrappedPrimitive(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isString() {
|
||||
return value instanceof String;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
String asString() {
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isNumber() {
|
||||
return value instanceof Number;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isBoolean() {
|
||||
return value instanceof Boolean;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean asBoolean() {
|
||||
return (Boolean) value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInByte() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInShort() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInInt() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInLong() {
|
||||
return value instanceof Long;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInFloat() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInDouble() {
|
||||
return value instanceof Double;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
byte asByte() throws UnsupportedMessageException {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
short asShort() throws UnsupportedMessageException {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
int asInt() throws UnsupportedMessageException {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
long asLong() throws UnsupportedMessageException {
|
||||
return (Long) value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
float asFloat() throws UnsupportedMessageException {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
double asDouble() throws UnsupportedMessageException {
|
||||
return (Double) value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean fitsInBigInteger() {
|
||||
return value instanceof BigInteger;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
BigInteger asBigInteger() throws UnsupportedMessageException {
|
||||
return (BigInteger) value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
String toDisplayString(boolean ignore) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
Object asDirect() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WrappedPrimitive[" + value + "]";
|
||||
}
|
||||
}
|
@ -246,7 +246,7 @@ object DistributionPackage {
|
||||
throw new RuntimeException(s"Cannot compile $libMajor.$libName.")
|
||||
}
|
||||
} else {
|
||||
log.info(s"No modified files. Not generating index for ${libName} ")
|
||||
log.debug(s"No modified files. Not generating index for ${libName}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,16 @@ foreign js call_function fn arg_1 = """
|
||||
|
||||
Number.foo self = "foo called"
|
||||
|
||||
from Standard.Base import all
|
||||
|
||||
type Fool
|
||||
Value fool
|
||||
|
||||
to_text : Text
|
||||
to_text self = "{FOOL " + self.fool.to_text + "}"
|
||||
|
||||
Fool.from (that : Any) = Fool.Value that
|
||||
|
||||
spec =
|
||||
Test.group "Conversion" <|
|
||||
Test.specify "should be able to convert atoms" <|
|
||||
@ -202,6 +212,145 @@ spec =
|
||||
to_6 (v : Number & Decimal & Integer) = v
|
||||
to_6 m . should_equal 1.5
|
||||
|
||||
Test.specify "Requesting Integer & Fool" <|
|
||||
do_number (x : Integer & Fool) =
|
||||
x.foo . should_equal "foo called"
|
||||
x.fool . should_equal 42
|
||||
x==x . should_be_true
|
||||
(x:Integer)==42 . should_be_true
|
||||
(x:Fool)==42 . should_be_false
|
||||
x==42 . should_be_true
|
||||
42==(x.to Integer) . should_be_true
|
||||
42==(x.to Fool) . should_be_false
|
||||
42==x . should_be_true
|
||||
100+(x:Integer) . should_equal 142
|
||||
(x:Integer)+100 . should_equal 142
|
||||
x+100 . should_equal 142
|
||||
100+x . should_equal 142
|
||||
x.to_text . should_equal "{FOOL 42}"
|
||||
(x:Fool).to_text . should_equal "{FOOL 42}"
|
||||
(x:Integer).to_text . should_equal "42"
|
||||
|
||||
do_number 42
|
||||
|
||||
Test.specify "Requesting Decimal & Fool" <|
|
||||
do_number (x : Decimal & Fool) =
|
||||
x.foo . should_equal "foo called"
|
||||
x.fool . should_equal 42.3
|
||||
x==x . should_be_true
|
||||
(x:Decimal)==42.3 . should_be_true
|
||||
(x:Fool)==42.3 . should_be_false
|
||||
x==42.3 . should_be_true
|
||||
42.3==(x.to Decimal) . should_be_true
|
||||
42.3==(x.to Fool) . should_be_false
|
||||
42.3==x . should_be_true
|
||||
100+(x:Decimal) . should_equal 142.3
|
||||
(x:Decimal)+100 . should_equal 142.3
|
||||
x+100 . should_equal 142.3
|
||||
100+x . should_equal 142.3
|
||||
x.to_text . should_equal "{FOOL 42.3}"
|
||||
(x:Fool).to_text . should_equal "{FOOL 42.3}"
|
||||
(x:Decimal).to_text . should_equal "42.3"
|
||||
|
||||
do_number 42.3
|
||||
|
||||
Test.specify "Requesting Boolean & Fool" <|
|
||||
do_boolean (x : Boolean & Fool) =
|
||||
x.fool . should_equal True
|
||||
x==x . should_be_true
|
||||
(x:Boolean) . should_be_true
|
||||
(x:Fool)==True . should_be_false
|
||||
x==True . should_be_true
|
||||
True==(x:Boolean) . should_be_true
|
||||
True==(x:Fool) . should_be_false
|
||||
True==x . should_be_true
|
||||
x.to_text . should_equal "{FOOL True}"
|
||||
(x:Fool).to_text . should_equal "{FOOL True}"
|
||||
(x:Boolean).to_text . should_equal "True"
|
||||
Panic.recover Any (x:Integer).to_text . should_fail_with Type_Error
|
||||
|
||||
do_boolean True
|
||||
|
||||
Test.specify "Requesting Text & Fool" <|
|
||||
do_text (x : Text & Fool) =
|
||||
x.fool . should_equal "Hello"
|
||||
x==x . should_be_true
|
||||
(x:Text)=="Hello" . should_be_true
|
||||
(x:Fool)=="Hello" . should_be_false
|
||||
x=="Hello" . should_be_true
|
||||
"Hello"==(x:Text) . should_be_true
|
||||
"Hello"==(x:Fool) . should_be_false
|
||||
"Hello"==x . should_be_true
|
||||
x.to_text . should_equal "Hello"
|
||||
(x:Fool).to_text . should_equal "{FOOL Hello}"
|
||||
(x:Text).to_text . should_equal "Hello"
|
||||
Panic.recover Any (x:Boolean).to_text . should_fail_with Type_Error
|
||||
|
||||
do_text "Hello"
|
||||
|
||||
Test.specify "Requesting Time_Of_Day & Fool" <|
|
||||
now = Time_Of_Day.now
|
||||
|
||||
do_time (x : Time_Of_Day & Fool) =
|
||||
x.fool . should_equal now
|
||||
x==x . should_be_true
|
||||
(x:Time_Of_Day)==now . should_be_true
|
||||
(x:Fool)==now . should_be_false
|
||||
x==now . should_be_true
|
||||
now==(x:Time_Of_Day) . should_be_true
|
||||
now==(x:Fool) . should_be_false
|
||||
now==x . should_be_true
|
||||
x.to_text . should_equal now.to_text
|
||||
|
||||
do_time now
|
||||
|
||||
Test.specify "Requesting Date & Fool" <|
|
||||
now = Date.today
|
||||
|
||||
do_date (x : Date & Fool) =
|
||||
x.fool . should_equal now
|
||||
x==x . should_be_true
|
||||
(x:Date)==now . should_be_true
|
||||
(x:Fool)==now . should_be_false
|
||||
x==now . should_be_true
|
||||
now==(x:Date) . should_be_true
|
||||
now==(x:Fool) . should_be_false
|
||||
now==x . should_be_true
|
||||
x.to_text . should_equal "{FOOL "+now.to_text+"}"
|
||||
|
||||
do_date now
|
||||
|
||||
Test.specify "Requesting Date_Time & Fool" <|
|
||||
now = Date_Time.now
|
||||
|
||||
do_time (x : Date_Time & Fool) =
|
||||
x.fool . should_equal now
|
||||
x==x . should_be_true
|
||||
(x:Date_Time)==now . should_be_true
|
||||
(x:Fool)==now . should_be_false
|
||||
x==now . should_be_true
|
||||
now==(x:Date_Time) . should_be_true
|
||||
now==(x:Fool) . should_be_false
|
||||
now==x . should_be_true
|
||||
x.to_text . should_equal now.to_text
|
||||
|
||||
do_time now
|
||||
|
||||
Test.specify "Requesting Duration & Fool" <|
|
||||
now = Duration.new hours=5
|
||||
|
||||
do_duration (x : Duration & Fool) =
|
||||
x.fool . should_equal now
|
||||
x==x . should_be_true
|
||||
(x:Duration)==now . should_be_true
|
||||
(x:Fool)==now . should_be_false
|
||||
x==now . should_be_true
|
||||
now==(x:Duration) . should_be_true
|
||||
now==(x:Fool) . should_be_false
|
||||
now==x . should_be_true
|
||||
x.to_text . should_equal "{FOOL "+now.to_text+"}"
|
||||
|
||||
do_duration now
|
||||
|
||||
Hello.from (that:Foo) suffix=" " = Hello.Say <| (that.foo.to_case Case.Upper) + suffix
|
||||
Hello.from (that:Bar) suffix="!" = Hello.Say <| (that.bar.to_case Case.Lower) + suffix
|
||||
|
Loading…
Reference in New Issue
Block a user