mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 04:43:26 +03:00
Unbounded Integers (#1134)
This commit is contained in:
parent
f9ce402a49
commit
7373da2f1f
@ -12,6 +12,7 @@ import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.runtime.builtin.Bool;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.builtin.Number;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
@ -19,6 +20,7 @@ import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Array;
|
||||
import org.enso.interpreter.runtime.error.MethodDoesNotExistException;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
/**
|
||||
* A node performing lookups of method definitions.
|
||||
@ -76,11 +78,21 @@ public abstract class MethodResolverNode extends Node {
|
||||
}
|
||||
|
||||
@Specialization(guards = "cachedSymbol == symbol")
|
||||
Function resolveNumber(
|
||||
Function resolveBigInteger(
|
||||
UnresolvedSymbol symbol,
|
||||
EnsoBigInteger self,
|
||||
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
||||
@Cached(value = "resolveMethodOnBigInteger(cachedSymbol)", allowUncached = true)
|
||||
Function function) {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Specialization(guards = "cachedSymbol == symbol")
|
||||
Function resolveLong(
|
||||
UnresolvedSymbol symbol,
|
||||
long self,
|
||||
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
||||
@Cached(value = "resolveMethodOnNumber(cachedSymbol)", allowUncached = true)
|
||||
@Cached(value = "resolveMethodOnLong(cachedSymbol)", allowUncached = true)
|
||||
Function function) {
|
||||
return function;
|
||||
}
|
||||
@ -190,9 +202,22 @@ public abstract class MethodResolverNode extends Node {
|
||||
return ensureMethodExists(symbol.resolveFor(cons, getBuiltins().any()), cons, symbol);
|
||||
}
|
||||
|
||||
Function resolveMethodOnNumber(UnresolvedSymbol symbol) {
|
||||
Function resolveMethodOnLong(UnresolvedSymbol symbol) {
|
||||
Number number = getBuiltins().number();
|
||||
return ensureMethodExists(
|
||||
symbol.resolveFor(getBuiltins().number(), getBuiltins().any()), "Number", symbol);
|
||||
symbol.resolveFor(
|
||||
number.getSmallInteger(), number.getInteger(), number.getNumber(), getBuiltins().any()),
|
||||
"Integer",
|
||||
symbol);
|
||||
}
|
||||
|
||||
Function resolveMethodOnBigInteger(UnresolvedSymbol symbol) {
|
||||
Number number = getBuiltins().number();
|
||||
return ensureMethodExists(
|
||||
symbol.resolveFor(
|
||||
number.getBigInteger(), number.getInteger(), number.getNumber(), getBuiltins().any()),
|
||||
"Integer",
|
||||
symbol);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "+", description = "Addition on numbers.")
|
||||
public class AddNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this + that;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "/", description = "Division for numbers.")
|
||||
public class DivideNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this / that;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "==", description = "Equality on numbers.")
|
||||
public class EqualsNode extends Node {
|
||||
boolean execute(long _this, long that) {
|
||||
return _this == that;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "%", description = "Modulo operation for numbers.")
|
||||
public class ModNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this % that;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "*", description = "Multiplication on numbers.")
|
||||
public class MultiplyNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this * that;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "negate", description = "Negation for numbers.")
|
||||
public class NegateNode extends Node {
|
||||
long execute(long _this) {
|
||||
return -_this;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Number", name = "-", description = "Subtraction on numbers.")
|
||||
public class SubtractNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this - that;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "+", description = "Big integer addition.")
|
||||
public abstract class AddNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static AddNode build() {
|
||||
return AddNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.+", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "/", description = "Big integer division.")
|
||||
public abstract class DivideNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer./", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "==", description = "Big integer equality.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInt(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.equals(_this.getValue(), that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "%", description = "Big integer modulo division.")
|
||||
public abstract class ModNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static ModNode build() {
|
||||
return ModNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.modulo(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.modulo(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.%", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "*", description = "Big integer multiplication.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static MultiplyNode build() {
|
||||
return MultiplyNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.*", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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 = "Big_Integer", name = "negate", description = "Big integer negation.")
|
||||
public class NegateNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
Object execute(EnsoBigInteger _this) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.negate(_this.getValue()));
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "-", description = "Big integer subtraction.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static SubtractNode build() {
|
||||
return SubtractNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.-", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "+", description = "Addition of numbers.")
|
||||
public abstract class AddNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static AddNode build() {
|
||||
return AddNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization(rewriteOn = ArithmeticException.class)
|
||||
long doLong(long _this, long that) {
|
||||
return Math.addExact(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doOverflow(long _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(that.getValue(), _this));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.+", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "/", description = "Division of numbers.")
|
||||
public abstract class DivideNode extends Node {
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doLong(long _this, long that) {
|
||||
return _this / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer./", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "==", description = "Equality on numbers.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(long _this, long that) {
|
||||
return _this == that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "%", description = "Modulo division of numbers.")
|
||||
public abstract class ModNode extends Node {
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static ModNode build() {
|
||||
return ModNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doLong(long _this, long that) {
|
||||
return _this % that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return _this;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.%", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "*", description = "Multiplication of numbers.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static MultiplyNode build() {
|
||||
return MultiplyNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization(rewriteOn = ArithmeticException.class)
|
||||
long doLong(long _this, long that) {
|
||||
return Math.multiplyExact(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doOverflow(long _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(that.getValue(), _this));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.*", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "negate", description = "Negation for numbers.")
|
||||
public abstract class NegateNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
static NegateNode build() {
|
||||
return NegateNodeGen.create();
|
||||
}
|
||||
|
||||
abstract Object execute(long _this);
|
||||
|
||||
@Specialization(rewriteOn = ArithmeticException.class)
|
||||
long doNormal(long _this) {
|
||||
return Math.negateExact(_this);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doOverflow(long _this) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.negate(_this));
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
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.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "-", description = "Subtraction of numbers.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static SubtractNode build() {
|
||||
return SubtractNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization(rewriteOn = ArithmeticException.class)
|
||||
long doLong(long _this, long that) {
|
||||
return Math.subtractExact(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doOverflow(long _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this, that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.-", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.utils;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/** Re-exposes big-integer operations behind a truffle boundary. */
|
||||
public class BigIntegerOps {
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger multiply(long a, long b) {
|
||||
return BigInteger.valueOf(a).multiply(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger multiply(BigInteger a, long b) {
|
||||
return a.multiply(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger multiply(BigInteger a, BigInteger b) {
|
||||
return a.multiply(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger add(long a, long b) {
|
||||
return BigInteger.valueOf(a).add(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger add(BigInteger a, long b) {
|
||||
return a.add(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger add(BigInteger a, BigInteger b) {
|
||||
return a.add(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger subtract(long a, long b) {
|
||||
return BigInteger.valueOf(a).subtract(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger subtract(BigInteger a, long b) {
|
||||
return a.subtract(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger subtract(long a, BigInteger b) {
|
||||
return BigInteger.valueOf(a).subtract(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger subtract(BigInteger a, BigInteger b) {
|
||||
return a.subtract(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger divide(BigInteger a, long b) {
|
||||
return a.divide(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger divide(BigInteger a, BigInteger b) {
|
||||
return a.divide(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger modulo(BigInteger a, long b) {
|
||||
return a.mod(BigInteger.valueOf(b));
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger modulo(BigInteger a, BigInteger b) {
|
||||
return a.mod(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger negate(BigInteger a) {
|
||||
return a.negate();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger negate(long a) {
|
||||
return BigInteger.valueOf(a).negate();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static boolean equals(BigInteger a, BigInteger b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.utils;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@ReportPolymorphism
|
||||
@NodeInfo(description = "Takes a big integer and casts it to a long, if the operation is safe.")
|
||||
public class ToEnsoNumberNode extends Node {
|
||||
private final ConditionProfile fitsProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private static final BigInteger MIN_LONG_BIGINT = BigInteger.valueOf(Long.MIN_VALUE);
|
||||
private static final BigInteger MAX_LONG_BIGINT = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
|
||||
/** @return a new instance of this node. */
|
||||
public static ToEnsoNumberNode build() {
|
||||
return new ToEnsoNumberNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the node.
|
||||
*
|
||||
* @param bigInteger the big integer to downcast.
|
||||
* @return a long with the same value if possible, the original integer wrapped in {@link
|
||||
* org.enso.interpreter.runtime.number.EnsoBigInteger} otherwise.
|
||||
*/
|
||||
public Object execute(BigInteger bigInteger) {
|
||||
if (fitsProfile.profile(fitsInLong(bigInteger))) {
|
||||
return toLong(bigInteger);
|
||||
}
|
||||
return new EnsoBigInteger(bigInteger);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private static boolean fitsInLong(BigInteger bigInteger) {
|
||||
return bigInteger.compareTo(MIN_LONG_BIGINT) >= 0 && bigInteger.compareTo(MAX_LONG_BIGINT) <= 0;
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private static long toLong(BigInteger bigInteger) {
|
||||
return bigInteger.longValue();
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.literal;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.node.ExpressionNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/** A representation of big integer literals in Enso. */
|
||||
@NodeInfo(shortName = "BigIntegerLiteral")
|
||||
public final class BigIntegerLiteralNode extends ExpressionNode {
|
||||
private final EnsoBigInteger value;
|
||||
|
||||
private BigIntegerLiteralNode(BigInteger value) {
|
||||
this.value = new EnsoBigInteger(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of this node.
|
||||
*
|
||||
* @param value the value for the node to represent
|
||||
* @return a node representing the literal given by {@code value}
|
||||
*/
|
||||
public static BigIntegerLiteralNode build(BigInteger value) {
|
||||
return new BigIntegerLiteralNode(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the literal.
|
||||
*
|
||||
* @param frame the stack frame for execution
|
||||
* @return the value of the integer literal
|
||||
*/
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
return this.value;
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@ import org.enso.interpreter.node.expression.builtin.interop.generic.*;
|
||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.MethodDispatchNode;
|
||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.ConstructorDispatchNode;
|
||||
import org.enso.interpreter.node.expression.builtin.io.*;
|
||||
import org.enso.interpreter.node.expression.builtin.number.*;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.GCMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.NoInlineMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.state.*;
|
||||
@ -46,7 +45,7 @@ public class Builtins {
|
||||
private final ModuleScope scope;
|
||||
private final AtomConstructor unit;
|
||||
private final AtomConstructor any;
|
||||
private final AtomConstructor number;
|
||||
private final Number number;
|
||||
private final AtomConstructor function;
|
||||
private final AtomConstructor text;
|
||||
private final AtomConstructor debug;
|
||||
@ -71,7 +70,6 @@ public class Builtins {
|
||||
scope = module.compileScope(context);
|
||||
unit = new AtomConstructor("Unit", scope).initializeFields();
|
||||
any = new AtomConstructor("Any", scope).initializeFields();
|
||||
number = new AtomConstructor("Number", scope).initializeFields();
|
||||
bool = new Bool(language, scope);
|
||||
error = new Error(language, scope);
|
||||
array = new Array(language, scope);
|
||||
@ -79,6 +77,7 @@ public class Builtins {
|
||||
text = new AtomConstructor("Text", scope).initializeFields();
|
||||
debug = new AtomConstructor("Debug", scope).initializeFields();
|
||||
system = new System(language, scope);
|
||||
number = new Number(language, scope);
|
||||
|
||||
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
||||
AtomConstructor cons =
|
||||
@ -96,10 +95,8 @@ public class Builtins {
|
||||
AtomConstructor thread = new AtomConstructor("Thread", scope).initializeFields();
|
||||
|
||||
AtomConstructor unsafe = new AtomConstructor("Unsafe", scope).initializeFields();
|
||||
|
||||
scope.registerConstructor(unit);
|
||||
scope.registerConstructor(any);
|
||||
scope.registerConstructor(number);
|
||||
scope.registerConstructor(function);
|
||||
scope.registerConstructor(text);
|
||||
|
||||
@ -131,14 +128,6 @@ public class Builtins {
|
||||
scope.registerMethod(error, "throw", ThrowErrorMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "catch", CatchErrorMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(number, "+", AddMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "-", SubtractMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "*", MultiplyMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "/", DivideMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "%", ModMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "negate", NegateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "==", EqualsMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(state, "get", GetStateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(state, "put", PutStateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(state, "run", RunStateMethodGen.makeFunction(language));
|
||||
@ -220,11 +209,11 @@ public class Builtins {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code Number} atom constructor.
|
||||
* Returns the number-related entities.
|
||||
*
|
||||
* @return the {@code Number} atom constructor
|
||||
* @return the number-related part of builtins.
|
||||
*/
|
||||
public AtomConstructor number() {
|
||||
public Number number() {
|
||||
return number;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,131 @@
|
||||
package org.enso.interpreter.runtime.builtin;
|
||||
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
|
||||
/** A container for all number-related builtins. */
|
||||
public class Number {
|
||||
private final AtomConstructor smallInteger;
|
||||
private final AtomConstructor bigInteger;
|
||||
private final AtomConstructor integer;
|
||||
private final AtomConstructor number;
|
||||
|
||||
/**
|
||||
* Creates and registers number builtins.
|
||||
*
|
||||
* @param language the current language instance.
|
||||
* @param scope the builtins scope.
|
||||
*/
|
||||
public Number(Language language, ModuleScope scope) {
|
||||
number = new AtomConstructor("Number", scope).initializeFields();
|
||||
smallInteger = new AtomConstructor("Small_Integer", scope).initializeFields();
|
||||
integer = new AtomConstructor("Integer", scope).initializeFields();
|
||||
bigInteger = new AtomConstructor("Big_Integer", scope).initializeFields();
|
||||
|
||||
registerInt64Methods(language, scope);
|
||||
registerBigIntegerMethods(language, scope);
|
||||
|
||||
scope.registerConstructor(number);
|
||||
scope.registerConstructor(smallInteger);
|
||||
scope.registerConstructor(integer);
|
||||
scope.registerConstructor(bigInteger);
|
||||
}
|
||||
|
||||
private void registerInt64Methods(Language language, ModuleScope scope) {
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"+",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.AddMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"-",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.SubtractMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"*",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.MultiplyMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"/",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.DivideMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"%",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.ModMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"negate",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.NegateMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"==",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.EqualsMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
private void registerBigIntegerMethods(Language language, ModuleScope scope) {
|
||||
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"+",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.AddMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"-",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.SubtractMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"*",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.MultiplyMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"/",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.DivideMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"%",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.ModMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"negate",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.NegateMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"==",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.EqualsMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
/** @return the Int64 atom constructor. */
|
||||
public AtomConstructor getSmallInteger() {
|
||||
return smallInteger;
|
||||
}
|
||||
|
||||
/** @return the Big_Integer atom constructor. */
|
||||
public AtomConstructor getBigInteger() {
|
||||
return bigInteger;
|
||||
}
|
||||
|
||||
/** @return the Integer atom constructor */
|
||||
public AtomConstructor getInteger() {
|
||||
return integer;
|
||||
}
|
||||
|
||||
/** @return the Number atom constructor */
|
||||
public AtomConstructor getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package org.enso.interpreter.runtime.number;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/** Internal wrapper for a {@link BigInteger}. */
|
||||
public class EnsoBigInteger {
|
||||
private final BigInteger value;
|
||||
|
||||
/**
|
||||
* Wraps a {@link BigInteger}.
|
||||
*
|
||||
* @param value the value to wrap.
|
||||
*/
|
||||
public EnsoBigInteger(BigInteger value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** @return the contained {@link BigInteger}. */
|
||||
public BigInteger getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.data.Array;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
/**
|
||||
* This class defines the interpreter-level type system for Enso.
|
||||
@ -33,7 +34,8 @@ import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
Thunk.class,
|
||||
RuntimeError.class,
|
||||
UnresolvedSymbol.class,
|
||||
Array.class
|
||||
Array.class,
|
||||
EnsoBigInteger.class
|
||||
})
|
||||
public class Types {
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.enso.compiler.codegen
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
import com.oracle.truffle.api.Truffle
|
||||
import com.oracle.truffle.api.source.{Source, SourceSection}
|
||||
import org.enso.compiler.core.IR
|
||||
@ -41,6 +43,7 @@ import org.enso.interpreter.node.expression.constant.{
|
||||
ErrorNode
|
||||
}
|
||||
import org.enso.interpreter.node.expression.literal.{
|
||||
BigIntegerLiteralNode,
|
||||
IntegerLiteralNode,
|
||||
TextLiteralNode
|
||||
}
|
||||
@ -857,7 +860,10 @@ class IrToTruffle(
|
||||
def processLiteral(literal: IR.Literal): RuntimeExpression =
|
||||
literal match {
|
||||
case IR.Literal.Number(value, location, _, _) =>
|
||||
setLocation(IntegerLiteralNode.build(value.toLong), location)
|
||||
val node = value.toLongOption
|
||||
.map(IntegerLiteralNode.build)
|
||||
.getOrElse(BigIntegerLiteralNode.build(new BigInteger(value)))
|
||||
setLocation(node, location)
|
||||
case IR.Literal.Text(text, location, _, _) =>
|
||||
setLocation(TextLiteralNode.build(text), location)
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ class ReplTest extends InterpreterTest with BeforeAndAfter with EitherValues {
|
||||
}
|
||||
eval(code)
|
||||
val errorMsg =
|
||||
"Unexpected type provided for argument `that` in Number.+"
|
||||
"Unexpected type provided for argument `that` in Integer.+"
|
||||
evalResult.left.value.getMessage shouldEqual errorMsg
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ class MethodsTest extends InterpreterTest {
|
||||
"""
|
||||
|main = foo 7
|
||||
|""".stripMargin
|
||||
the[InterpreterException] thrownBy eval(code) should have message "Object Number does not define method foo."
|
||||
the[InterpreterException] thrownBy eval(code) should have message "Object Integer does not define method foo."
|
||||
}
|
||||
|
||||
"be callable for any type when defined on Any" in {
|
||||
|
@ -41,7 +41,7 @@ sum_state = sum_to ->
|
||||
main =
|
||||
hundred_mil = 100000000
|
||||
IO.println "Measuring SumTCO"
|
||||
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10
|
||||
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 500 10
|
||||
IO.println "Measuring SumTCO Java"
|
||||
Bench_Utils.measure (here.sum_tco_java hundred_mil) "sum_tco" 100 10
|
||||
IO.println "Measuring State"
|
||||
|
@ -7,6 +7,7 @@ import Test.Names_Spec
|
||||
import Test.Process_Spec
|
||||
import Test.Java_Interop.Spec as Java_Spec
|
||||
import Test.Vector.Spec as Vector_Spec
|
||||
import Test.Numbers.Spec as Numbers_Spec
|
||||
|
||||
main = Test.Suite.runMain <|
|
||||
List_Spec.spec
|
||||
@ -17,3 +18,4 @@ main = Test.Suite.runMain <|
|
||||
Process_Spec.spec
|
||||
Java_Spec.spec
|
||||
Vector_Spec.spec
|
||||
Numbers_Spec.spec
|
||||
|
37
test/Test/src/Numbers/Spec.enso
Normal file
37
test/Test/src/Numbers/Spec.enso
Normal file
@ -0,0 +1,37 @@
|
||||
from Base import all
|
||||
|
||||
import Base.Test
|
||||
|
||||
Integer.is_even = this % 2 == 0
|
||||
|
||||
spec =
|
||||
almost_max_long = 9223372036854775806
|
||||
almost_max_long_times_three = 27670116110564327418
|
||||
hundred_factorial = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
||||
describe "Integers" <|
|
||||
it "should be of unbound size when multiplied" <|
|
||||
1.upto 101 . fold 1 (*) . should_equal hundred_factorial
|
||||
it "should be of unbound size when added" <|
|
||||
(almost_max_long + almost_max_long + almost_max_long).should_equal almost_max_long_times_three
|
||||
it "should be of unbound size when subtracted" <|
|
||||
(0 - almost_max_long - almost_max_long - almost_max_long).should_equal almost_max_long_times_three.negate
|
||||
it "should be of unbound size when dividing" <|
|
||||
expected = 3372816184472482867110284450043137767873196479305249187406461598235841786750685581361224832688174410089430537516012695688121622150430744676
|
||||
((1.upto 101 . fold 1 (*)) / 3*almost_max_long).should_equal expected
|
||||
it "should be of unbound size when taking remainder" <|
|
||||
expected = 3191479909175673432
|
||||
((1.upto 101 . fold 1 (*)) % 3*almost_max_long).should_equal expected
|
||||
it "should allow defining extension methods through the Integer type for any number size" <|
|
||||
876543.is_even.should_be_false
|
||||
(1.upto 101 . fold 1 (*)).is_even.should_be_true
|
||||
it "should handle the negation edge cases" <|
|
||||
x = 9223372036854775808
|
||||
y = -x
|
||||
z = -9223372036854775808
|
||||
y.should_equal z
|
||||
it "should handle equality between small and big integers" <|
|
||||
(1 == hundred_factorial).should_be_false
|
||||
(hundred_factorial == 1).should_be_false
|
||||
it "should properly handle going to big numbers and back" <|
|
||||
((almost_max_long * 3) / 3) . should_equal almost_max_long
|
||||
|
Loading…
Reference in New Issue
Block a user