mirror of
https://github.com/enso-org/enso.git
synced 2024-11-26 08:52:58 +03:00
Executing (parts of) Truffle TCK with Enso values (#8685)
This commit is contained in:
parent
ed410a8332
commit
0e6952710a
35
build.sbt
35
build.sbt
@ -1503,7 +1503,11 @@ lazy val `runtime-test-instruments` =
|
||||
JPMSUtils.filterModulesFromUpdate(
|
||||
update.value,
|
||||
GraalVM.modules ++ Seq(
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck-tests" % graalMavenPackagesVersion,
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion
|
||||
),
|
||||
streams.value.log,
|
||||
shouldContainAll = true
|
||||
@ -1511,6 +1515,7 @@ lazy val `runtime-test-instruments` =
|
||||
},
|
||||
libraryDependencies ++= GraalVM.modules,
|
||||
libraryDependencies ++= Seq(
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion,
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided"
|
||||
)
|
||||
)
|
||||
@ -1553,6 +1558,12 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
},
|
||||
Test / parallelExecution := false,
|
||||
Test / logBuffered := false,
|
||||
Test / javaOptions ++= Seq(
|
||||
"-Dtck.values=java-host,enso",
|
||||
"-Dtck.language=enso",
|
||||
"-Dtck.inlineVerifierInstrument=false",
|
||||
"-Dpolyglot.engine.AllowExperimentalOptions=true"
|
||||
),
|
||||
scalacOptions += "-Ymacro-annotations",
|
||||
scalacOptions ++= Seq("-Ypatmat-exhaust-depth", "off"),
|
||||
libraryDependencies ++= jmh ++ jaxb ++ GraalVM.langsPkgs ++ Seq(
|
||||
@ -1562,8 +1573,9 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-dsl-processor" % graalMavenPackagesVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalMavenPackagesVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalMavenPackagesVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalMavenPackagesVersion % Test,
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalMavenPackagesVersion % Test,
|
||||
"org.graalvm.truffle" % "truffle-tck-tests" % graalMavenPackagesVersion % Test,
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided",
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.scalactic" %% "scalactic" % scalacticVersion % Test,
|
||||
@ -1599,8 +1611,12 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
val updateReport = (Test / update).value
|
||||
val requiredModIds =
|
||||
GraalVM.modules ++ GraalVM.langsPkgs ++ GraalVM.insightPkgs ++ logbackPkg ++ Seq(
|
||||
"org.slf4j" % "slf4j-api" % slf4jVersion,
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion
|
||||
"org.slf4j" % "slf4j-api" % slf4jVersion,
|
||||
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion,
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalMavenPackagesVersion,
|
||||
"org.graalvm.truffle" % "truffle-tck-tests" % graalMavenPackagesVersion
|
||||
)
|
||||
val requiredMods = JPMSUtils.filterModulesFromUpdate(
|
||||
updateReport,
|
||||
@ -1659,7 +1675,11 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
Map(
|
||||
// We patched the test-classes into the runtime module. These classes access some stuff from
|
||||
// unnamed module. Thus, let's add ALL-UNNAMED.
|
||||
runtimeModName -> Seq("ALL-UNNAMED", testInstrumentsModName),
|
||||
runtimeModName -> Seq(
|
||||
"ALL-UNNAMED",
|
||||
testInstrumentsModName,
|
||||
"truffle.tck.tests"
|
||||
),
|
||||
testInstrumentsModName -> Seq(runtimeModName)
|
||||
)
|
||||
},
|
||||
@ -1668,7 +1688,8 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
.settings(
|
||||
Test / fork := true,
|
||||
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
|
||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
|
||||
"ENSO_TEST_DISABLE_IR_CACHE" -> "false",
|
||||
"ENSO_EDITION_PATH" -> file("distribution/editions").getCanonicalPath
|
||||
),
|
||||
Test / compile := (Test / compile)
|
||||
.dependsOn(`runtime-fat-jar` / Compile / compileModuleInfo)
|
||||
|
@ -1,10 +1,15 @@
|
||||
module org.enso.runtime.test {
|
||||
requires org.graalvm.truffle;
|
||||
requires org.openide.util.lookup.RELEASE180;
|
||||
requires org.graalvm.polyglot;
|
||||
requires org.graalvm.polyglot_tck;
|
||||
|
||||
exports org.enso.interpreter.test.instruments;
|
||||
exports org.enso.interpreter.test.instruments.service;
|
||||
|
||||
provides org.graalvm.polyglot.tck.LanguageProvider with
|
||||
org.enso.interpreter.test.instruments.tck.EnsoTckLanguageProvider;
|
||||
|
||||
provides com.oracle.truffle.api.instrumentation.provider.TruffleInstrumentProvider with
|
||||
org.enso.interpreter.test.instruments.CodeIdsTestInstrumentProvider,
|
||||
org.enso.interpreter.test.instruments.CodeLocationsTestInstrumentProvider,
|
||||
|
@ -0,0 +1,86 @@
|
||||
package org.enso.interpreter.test.instruments.tck;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.Source;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.graalvm.polyglot.tck.LanguageProvider;
|
||||
import org.graalvm.polyglot.tck.Snippet;
|
||||
import org.graalvm.polyglot.tck.TypeDescriptor;
|
||||
|
||||
public class EnsoTckLanguageProvider implements LanguageProvider {
|
||||
public EnsoTckLanguageProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "enso";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value createIdentityFunction(Context context) {
|
||||
var id = context.eval("enso", """
|
||||
id a = a
|
||||
""").invokeMember("eval_expression", "id");
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Snippet> createValueConstructors(Context context) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Snippet> createExpressions(Context context) {
|
||||
var plus = context.eval("enso", """
|
||||
plus a b = a + b
|
||||
""").invokeMember("eval_expression", "plus");
|
||||
|
||||
return List.of(
|
||||
Snippet.newBuilder("plus:Number", plus, TypeDescriptor.NUMBER)
|
||||
.parameterTypes(TypeDescriptor.NUMBER, TypeDescriptor.NUMBER)
|
||||
.build(),
|
||||
Snippet.newBuilder("plus:Text", plus, TypeDescriptor.STRING)
|
||||
.parameterTypes(TypeDescriptor.STRING, TypeDescriptor.STRING)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Snippet> createStatements(Context context) {
|
||||
var when = context.eval("enso", """
|
||||
when c = if c then 1 else -1
|
||||
""").invokeMember("eval_expression", "when");;
|
||||
var which = context.eval("enso", """
|
||||
which c = case c of
|
||||
0 -> "zero"
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
_ -> "a lot"
|
||||
""").invokeMember("eval_expression", "which");
|
||||
return List.of(
|
||||
Snippet.newBuilder("if", when, TypeDescriptor.NUMBER)
|
||||
.parameterTypes(TypeDescriptor.BOOLEAN)
|
||||
.build(),
|
||||
Snippet.newBuilder("if", which, TypeDescriptor.STRING)
|
||||
.parameterTypes(TypeDescriptor.NUMBER)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Snippet> createScripts(Context context) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Source> createInvalidSyntaxScripts(Context context) {
|
||||
return List.of(
|
||||
Source.newBuilder("enso", """
|
||||
main = x + 2
|
||||
""", "unknown_x.enso").buildLiteral()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,22 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
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.GenerateUncached;
|
||||
import com.oracle.truffle.api.dsl.NeverDefault;
|
||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||
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 org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.node.expression.foreign.CoerceNothing;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.error.WarningsLibrary;
|
||||
|
||||
/**
|
||||
* Converts a value returned by a polyglot call back to a value that can be further used within Enso
|
||||
@ -63,21 +57,8 @@ public abstract class HostValueToEnsoNode extends Node {
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doChar(char i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Specialization(guards = {"n != null", "iop.fitsInBigInteger(n)", "!warnings.hasWarnings(n)"})
|
||||
Object doBigIntegerConversion(
|
||||
TruffleObject n,
|
||||
@Shared("iop") @CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@CachedLibrary(limit = "3") WarningsLibrary warnings,
|
||||
@Cached ToEnsoNumberNode to) {
|
||||
try {
|
||||
return to.execute(iop.asBigInteger(n));
|
||||
} catch (UnsupportedMessageException e) {
|
||||
throw CompilerDirectives.shouldNotReachHere(e);
|
||||
}
|
||||
Text doChar(char i) {
|
||||
return Text.create(Character.toString(i));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@ -88,7 +69,7 @@ public abstract class HostValueToEnsoNode extends Node {
|
||||
@Specialization(guards = {"o != null", "iop.isNull(o)"})
|
||||
Object doNull(
|
||||
Object o,
|
||||
@Shared("iop") @CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@CachedLibrary(limit = "3") InteropLibrary iop,
|
||||
@Cached CoerceNothing coerceNothing) {
|
||||
return coerceNothing.execute(o);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Specialization(guards = "interop.isBoolean(other)")
|
||||
@Specialization
|
||||
boolean equalsBoolInterop(
|
||||
boolean self,
|
||||
Object other,
|
||||
@ -106,7 +106,17 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Specialization(guards = "interop.fitsInLong(other)")
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsLongBigInt(long self, EnsoBigInteger other) {
|
||||
if (BigIntegerOps.fitsInLong(other.getValue())) {
|
||||
return BigInteger.valueOf(self).compareTo(other.getValue()) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean equalsLongInterop(
|
||||
long self,
|
||||
Object other,
|
||||
@ -137,46 +147,57 @@ public abstract class EqualsNode extends Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsDoubleBigInt(double self, EnsoBigInteger other) {
|
||||
return self == other.getValue().doubleValue();
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsBigIntBigInt(EnsoBigInteger self, EnsoBigInteger otherBigInt) {
|
||||
return self.equals(otherBigInt);
|
||||
boolean equalsDoubleInterop(
|
||||
double self,
|
||||
Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop) {
|
||||
try {
|
||||
if (interop.fitsInDouble(other)) {
|
||||
return self == interop.asDouble(other);
|
||||
}
|
||||
var otherBig = interop.asBigInteger(other);
|
||||
return self == asDouble(otherBig);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsBitIntDouble(EnsoBigInteger self, double other) {
|
||||
return self.getValue().doubleValue() == other;
|
||||
private static double asDouble(BigInteger big) {
|
||||
return big.doubleValue();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@Specialization(guards = {"isBigInteger(iop, self)", "isBigInteger(iop, other)"})
|
||||
@TruffleBoundary
|
||||
boolean equalsBigIntLong(EnsoBigInteger self, long other) {
|
||||
if (BigIntegerOps.fitsInLong(self.getValue())) {
|
||||
return self.getValue().compareTo(BigInteger.valueOf(other)) == 0;
|
||||
boolean other(
|
||||
Object self,
|
||||
Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
return asBigInteger(iop, self).equals(asBigInteger(iop, other));
|
||||
}
|
||||
|
||||
@Specialization(guards = "isBigInteger(iop, self)")
|
||||
@TruffleBoundary
|
||||
boolean equalsBigIntDouble(
|
||||
Object self,
|
||||
double other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
return asBigInteger(iop, self).doubleValue() == other;
|
||||
}
|
||||
|
||||
@Specialization(guards = "isBigInteger(iop, self)")
|
||||
@TruffleBoundary
|
||||
boolean equalsBigIntLong(
|
||||
Object self, long other, @Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
var v = asBigInteger(iop, self);
|
||||
if (BigIntegerOps.fitsInLong(v)) {
|
||||
return v.compareTo(BigInteger.valueOf(other)) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -193,29 +214,19 @@ public abstract class EqualsNode extends Node {
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
@Specialization(guards = {"!isPrimitiveValue(other)", "interop.fitsInBigInteger(other)"})
|
||||
@Specialization(guards = {"isBigInteger(iop, self)", "!isPrimitiveValue(other)"})
|
||||
boolean equalsBigIntInterop(
|
||||
EnsoBigInteger self,
|
||||
Object self,
|
||||
Object other,
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop) {
|
||||
@Shared("interop") @CachedLibrary(limit = "10") InteropLibrary iop) {
|
||||
try {
|
||||
var otherBigInteger = InteropLibrary.getUncached().asBigInteger(other);
|
||||
return self.asBigInteger().equals(otherBigInteger);
|
||||
return asBigInteger(iop, self).equals(otherBigInteger);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
boolean equalsLongBigInt(long self, EnsoBigInteger other) {
|
||||
if (BigIntegerOps.fitsInLong(other.getValue())) {
|
||||
return BigInteger.valueOf(self).compareTo(other.getValue()) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization(guards = {"selfText.is_normalized()", "otherText.is_normalized()"})
|
||||
boolean equalsTextText(Text selfText, Text otherText) {
|
||||
return selfText.toString().compareTo(otherText.toString()) == 0;
|
||||
@ -242,12 +253,13 @@ public abstract class EqualsNode extends Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares interop strings according to the lexicographical order, handling Unicode
|
||||
* normalization. See {@code Text_Utils.compare_to}.
|
||||
* Compares interop string with other object. If the other object doesn't support conversion to
|
||||
* String, it is not equal. Otherwise the two strings are compared according to the
|
||||
* lexicographical order, handling Unicode normalization. See {@code Text_Utils.compare_to}.
|
||||
*/
|
||||
@TruffleBoundary
|
||||
@Specialization(
|
||||
guards = {"selfInterop.isString(selfString)", "otherInterop.isString(otherString)"},
|
||||
guards = {"selfInterop.isString(selfString)"},
|
||||
limit = "3")
|
||||
boolean equalsStrings(
|
||||
Object selfString,
|
||||
@ -260,7 +272,7 @@ public abstract class EqualsNode extends Node {
|
||||
selfJavaString = selfInterop.asString(selfString);
|
||||
otherJavaString = otherInterop.asString(otherString);
|
||||
} catch (UnsupportedMessageException e) {
|
||||
throw EnsoContext.get(this).raiseAssertionPanic(this, null, e);
|
||||
return false;
|
||||
}
|
||||
return Core_Text_Utils.equals(selfJavaString, otherJavaString);
|
||||
}
|
||||
@ -371,4 +383,24 @@ public abstract class EqualsNode extends Node {
|
||||
static boolean isPrimitiveValue(Object object) {
|
||||
return object instanceof Boolean || object instanceof Long || object instanceof Double;
|
||||
}
|
||||
|
||||
static boolean isBigInteger(InteropLibrary iop, Object v) {
|
||||
if (v instanceof EnsoBigInteger) {
|
||||
return true;
|
||||
} else {
|
||||
return !iop.fitsInDouble(v) && !iop.fitsInLong(v) && iop.fitsInBigInteger(v);
|
||||
}
|
||||
}
|
||||
|
||||
BigInteger asBigInteger(InteropLibrary iop, Object v) {
|
||||
if (v instanceof EnsoBigInteger big) {
|
||||
return big.getValue();
|
||||
} else {
|
||||
try {
|
||||
return iop.asBigInteger(v);
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
throw EnsoContext.get(this).raiseAssertionPanic(this, "Expecting BigInteger", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,17 @@ public abstract class HashCodeNode extends Node {
|
||||
return bigInteger.getValue().hashCode();
|
||||
}
|
||||
|
||||
@Specialization(guards = {"!interop.fitsInLong(v)", "interop.fitsInBigInteger(v)"})
|
||||
@TruffleBoundary
|
||||
long hashCodeForBigInteger(
|
||||
Object v, @Shared("interop") @CachedLibrary(limit = "10") InteropLibrary interop) {
|
||||
try {
|
||||
return interop.asBigInteger(v).hashCode();
|
||||
} catch (UnsupportedMessageException ex) {
|
||||
throw EnsoContext.get(this).raiseAssertionPanic(this, "Expecting BigInteger", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long hashCodeForAtomConstructor(AtomConstructor atomConstructor) {
|
||||
// AtomConstructors are singletons, we take system hash code explicitly.
|
||||
|
@ -135,7 +135,9 @@ public abstract class TypeOfNode extends Node {
|
||||
Object value,
|
||||
@Shared("interop") @CachedLibrary(limit = "3") InteropLibrary interop) {
|
||||
Builtins builtins = EnsoContext.get(this).getBuiltins();
|
||||
if (interop.fitsInInt(value)) {
|
||||
if (interop.fitsInLong(value)) {
|
||||
return builtins.number().getInteger();
|
||||
} else if (interop.fitsInBigInteger(value)) {
|
||||
return builtins.number().getInteger();
|
||||
} else if (interop.fitsInDouble(value)) {
|
||||
return builtins.number().getFloat();
|
||||
|
@ -14,6 +14,7 @@ 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.interpreter.runtime.number.EnsoBigInteger;
|
||||
import org.enso.polyglot.MethodNames;
|
||||
import org.graalvm.polyglot.Context;
|
||||
import org.graalvm.polyglot.Value;
|
||||
@ -180,6 +181,58 @@ public class EqualsTest extends TestBase {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleEqualsEnsoBigInteger() {
|
||||
long value = Long.MIN_VALUE;
|
||||
double javaNumber = Math.pow(value, 10);
|
||||
var ensoNumber = new EnsoBigInteger(BigInteger.valueOf(value).pow(10));
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(javaNumber + " == " + ensoNumber, equalsNode.execute(javaNumber, ensoNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnsoBigIntegerEqualsDoubleEquals() {
|
||||
long value = Long.MIN_VALUE;
|
||||
double javaNumber = Math.pow(value, 10);
|
||||
var ensoNumber = new EnsoBigInteger(BigInteger.valueOf(value).pow(10));
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(ensoNumber + " == " + javaNumber, equalsNode.execute(ensoNumber, javaNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleEqualsJavaBigInteger() {
|
||||
long value = Long.MIN_VALUE;
|
||||
double javaNumber = Math.pow(value, 10);
|
||||
var hostNumber = unwrapValue(context, context.asValue(BigInteger.valueOf(value).pow(10)));
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(javaNumber + " == " + hostNumber, equalsNode.execute(javaNumber, hostNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJavaBigIntegerEqualsDoubleEquals() {
|
||||
long value = Long.MIN_VALUE;
|
||||
double javaNumber = Math.pow(value, 10);
|
||||
var hostNumber = unwrapValue(context, context.asValue(BigInteger.valueOf(value).pow(10)));
|
||||
executeInContext(
|
||||
context,
|
||||
() -> {
|
||||
assertTrue(hostNumber + " == " + javaNumber, equalsNode.execute(hostNumber, javaNumber));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVectorsEquality() {
|
||||
Object ensoVector =
|
||||
|
@ -215,6 +215,29 @@ public class MetaObjectTest extends TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numbersAreEitherIntegerOrFloat() throws Exception {
|
||||
var g = generator();
|
||||
var sn =
|
||||
ctx.eval(
|
||||
"enso",
|
||||
"""
|
||||
from Standard.Base import Meta
|
||||
|
||||
sn v = Meta.get_simple_type_name v
|
||||
""")
|
||||
.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "sn");
|
||||
for (var v : g.numbers()) {
|
||||
var simpleName = sn.execute(v).asString();
|
||||
var ok =
|
||||
switch (simpleName) {
|
||||
case "Integer", "Float" -> true;
|
||||
default -> false;
|
||||
};
|
||||
assertTrue("Unexpected simple name for number: " + v + " is " + simpleName, ok);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareQualifiedAndSimpleTypeName() throws Exception {
|
||||
var g = generator();
|
||||
|
@ -5,6 +5,7 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@ -394,6 +395,9 @@ class ValuesGenerator {
|
||||
collect.add(ctx.asValue((float) Math.PI));
|
||||
collect.add(ctx.asValue((double) Math.E));
|
||||
collect.add(ctx.asValue(Double.NaN));
|
||||
collect.add(ctx.asValue(BigInteger.valueOf(10).pow(40)));
|
||||
collect.add(ctx.asValue(BigInteger.valueOf(10).pow(40).doubleValue()));
|
||||
collect.add(ctx.asValue(BigInteger.valueOf(10).pow(40).doubleValue() + 1.0));
|
||||
}
|
||||
|
||||
for (var v : collect) {
|
||||
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckErrorTypeTest extends com.oracle.truffle.tck.tests.ErrorTypeTest {
|
||||
public EnsoTckErrorTypeTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckExpressionTest extends com.oracle.truffle.tck.tests.ExpressionTest {
|
||||
public EnsoTckExpressionTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckIdentityFunctionTest extends com.oracle.truffle.tck.tests.IdentityFunctionTest {
|
||||
public EnsoTckIdentityFunctionTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckInlineExecutionTest extends com.oracle.truffle.tck.tests.InlineExecutionTest {
|
||||
public EnsoTckInlineExecutionTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(null); // cannot access com.oracle.truffle.tck.tests.InlineTestRun
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckScriptTest extends com.oracle.truffle.tck.tests.ScriptTest {
|
||||
public EnsoTckScriptTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckStatementTest extends com.oracle.truffle.tck.tests.StatementTest {
|
||||
public EnsoTckStatementTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckTypeDescriptorTest extends com.oracle.truffle.tck.tests.TypeDescriptorTest {
|
||||
public EnsoTckTypeDescriptorTest() {}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.enso.interpreter.test.tck;
|
||||
|
||||
public class EnsoTckValueTest extends com.oracle.truffle.tck.tests.ValueTest {
|
||||
public EnsoTckValueTest(com.oracle.truffle.tck.tests.TestRun r) {
|
||||
super(r);
|
||||
}
|
||||
}
|
@ -52,8 +52,8 @@ public class Text_Utils {
|
||||
* @param str the string to convert
|
||||
* @return the UTF-16 character representation of the string.
|
||||
*/
|
||||
public static char[] get_chars(String str) {
|
||||
return str.toCharArray();
|
||||
public static int[] get_chars(String str) {
|
||||
return str.chars().toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.enso.base.polyglot;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import org.graalvm.polyglot.Value;
|
||||
@ -7,7 +8,8 @@ import org.graalvm.polyglot.Value;
|
||||
public class Polyglot_Utils {
|
||||
/**
|
||||
* Converts a polyglot Value ensuring that various date/time types are converted to the correct
|
||||
* type.
|
||||
* type. The conversion checks if a {@link java.math.BigInteger} fits into {@code long} and if so,
|
||||
* it converts it to {@code long}.
|
||||
*/
|
||||
public static Object convertPolyglotValue(Value item) {
|
||||
if (item == null) {
|
||||
@ -33,8 +35,11 @@ public class Polyglot_Utils {
|
||||
if (item.isException()) {
|
||||
throw new WrappedDataflowError(item);
|
||||
}
|
||||
|
||||
return item.as(Object.class);
|
||||
var ret = item.as(Object.class);
|
||||
if (ret instanceof BigInteger && item.fitsInLong()) {
|
||||
return item.asLong();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,7 +129,7 @@ read_characters decoder n =
|
||||
transfer_codepoints _ =
|
||||
if buffer.hasRemaining.not then Nothing else
|
||||
char = buffer.get
|
||||
v.append char
|
||||
v.append char.codepoints.first
|
||||
@Tail_Call transfer_codepoints Nothing
|
||||
transfer_codepoints Nothing
|
||||
v.to_vector
|
||||
|
Loading…
Reference in New Issue
Block a user