From f9a00c6a2a7612af536550c75c7df94ce52410af Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 27 Nov 2024 19:59:45 +0100 Subject: [PATCH 01/44] Add BuiltinsExposeMethodsTest --- .../builtins/BuiltinsExposeMethodsTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java new file mode 100644 index 000000000000..afe2c9143214 --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java @@ -0,0 +1,52 @@ +package org.enso.interpreter.test.builtins; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import com.oracle.truffle.api.interop.InteropLibrary; +import org.enso.interpreter.node.callable.InvokeMethodNode; +import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.atom.AtomNewInstanceNode; +import org.enso.interpreter.test.ValuesGenerator; +import org.enso.interpreter.test.ValuesGenerator.Language; +import org.enso.test.utils.ContextUtils; +import org.graalvm.polyglot.Context; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BuiltinsExposeMethodsTest { + private static Context ctx; + private static EnsoContext ensoCtx; + private static ValuesGenerator valuesGenerator; + + @BeforeClass + public static void initCtx() { + ctx = ContextUtils.createDefaultContext(); + ensoCtx = ContextUtils.leakContext(ctx); + valuesGenerator = ValuesGenerator.create(ctx, Language.ENSO); + } + + @AfterClass + public static void disposeCtx() { + ctx.close(); + ctx = null; + ensoCtx = null; + valuesGenerator.dispose(); + valuesGenerator = null; + } + + @Test + public void booleanExportsMethods() { + var src = """ + import Standard.Base.Runtime.Ref.Ref + main = + Ref.new 0 + """; + var ref = ContextUtils.evalModule(ctx, src); + assertThat("'get' member is invocable", + ref.canInvokeMember("get"), is(true)); + } +} From 587904a134f6a4bbccb7d2323fc8a7be1d8bf721 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 27 Nov 2024 20:28:34 +0100 Subject: [PATCH 02/44] typo in docs --- .../main/java/org/enso/interpreter/runtime/data/atom/Atom.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/atom/Atom.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/atom/Atom.java index 0666db5fdecf..abbd9694f29a 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/atom/Atom.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/atom/Atom.java @@ -155,7 +155,7 @@ boolean hasMembers() { /** * Returns list of fields of the Atom. If {@code includeInternal} is true, all methods, including - * project-private, are included. Fields are returned as filed getters, i.e., methods. Only fields + * project-private, are included. Fields are returned as field getters, i.e., methods. Only fields * for the constructor that was used to construct this atom are returned. */ @ExportMessage From bdbe60f13c4ef323b269bdd64b31b712abd881f5 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Fri, 29 Nov 2024 16:48:48 +0100 Subject: [PATCH 03/44] Test iteartes all the builtins and checks that all methods are invocable member --- .../builtins/BuiltinsExposeMethodsTest.java | 124 ++++++++++++++---- 1 file changed, 97 insertions(+), 27 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java index afe2c9143214..63712d49ff0e 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java @@ -4,49 +4,119 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import com.oracle.truffle.api.interop.InteropLibrary; -import org.enso.interpreter.node.callable.InvokeMethodNode; -import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.atom.AtomNewInstanceNode; +import java.util.ArrayList; +import java.util.List; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.library.dispatch.TypeOfNode; import org.enso.interpreter.test.ValuesGenerator; import org.enso.interpreter.test.ValuesGenerator.Language; import org.enso.test.utils.ContextUtils; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +/** + * Gathers all the builtin objects from {@link ValuesGenerator}. From their types, gathers all their + * methods via their {@link org.enso.interpreter.runtime.scope.ModuleScope definition scope} and + * checks that {@link Value#canInvokeMember(String)} returns true. + */ +@RunWith(Parameterized.class) public class BuiltinsExposeMethodsTest { private static Context ctx; - private static EnsoContext ensoCtx; - private static ValuesGenerator valuesGenerator; - @BeforeClass - public static void initCtx() { - ctx = ContextUtils.createDefaultContext(); - ensoCtx = ContextUtils.leakContext(ctx); - valuesGenerator = ValuesGenerator.create(ctx, Language.ENSO); + private final ValueWithType valueWithType; + + public BuiltinsExposeMethodsTest(ValueWithType valueWithType) { + this.valueWithType = valueWithType; + } + + private static Context ctx() { + if (ctx == null) { + ctx = ContextUtils.createDefaultContext(); + } + return ctx; + } + + @Parameters(name = "{index}: {0}") + public static Iterable generateBuiltinObjects() { + var valuesGenerator = ValuesGenerator.create(ctx(), Language.ENSO); + var builtinObjectsWithTypes = new ArrayList(); + ContextUtils.executeInContext( + ctx(), + () -> { + valuesGenerator.allValues().stream() + .map(val -> new ValueWithType(val, getType(val))) + .filter(valWithType -> !shouldSkipType(valWithType.type)) + .filter(valWithType -> !isPrimitive(valWithType.value)) + .forEach(builtinObjectsWithTypes::add); + return null; + }); + return builtinObjectsWithTypes; + } + + private static Type getType(Value object) { + var unwrapped = ContextUtils.unwrapValue(ctx(), object); + return TypeOfNode.getUncached().findTypeOrNull(unwrapped); } @AfterClass public static void disposeCtx() { - ctx.close(); - ctx = null; - ensoCtx = null; - valuesGenerator.dispose(); - valuesGenerator = null; + if (ctx != null) { + ctx.close(); + ctx = null; + } } @Test - public void booleanExportsMethods() { - var src = """ - import Standard.Base.Runtime.Ref.Ref - main = - Ref.new 0 - """; - var ref = ContextUtils.evalModule(ctx, src); - assertThat("'get' member is invocable", - ref.canInvokeMember("get"), is(true)); + public void builtinExposeMethods() { + ContextUtils.executeInContext( + ctx(), + () -> { + assertThat(valueWithType, is(notNullValue())); + assertThat(valueWithType.type.isBuiltin(), is(true)); + var typeDefScope = valueWithType.type.getDefinitionScope(); + var methodsDefinedInScope = typeDefScope.getMethodsForType(valueWithType.type); + if (methodsDefinedInScope != null) { + for (var methodInScope : methodsDefinedInScope) { + var methodName = methodInScope.getName(); + if (methodName.contains(".")) { + var items = methodName.split("\\."); + methodName = items[items.length - 1]; + } + assertThat( + "Member " + methodName + " should be invocable", + valueWithType.value.canInvokeMember(methodName), + is(true)); + } + } + return null; + }); + } + + private static boolean isPrimitive(Value object) { + var unwrapped = ContextUtils.unwrapValue(ctx(), object); + return unwrapped instanceof Long + || unwrapped instanceof Boolean + || unwrapped instanceof Integer + || unwrapped instanceof Double; } + + private static boolean shouldSkipType(Type type) { + if (type == null) { + return true; + } + if (!type.isBuiltin()) { + return true; + } + var builtins = ContextUtils.leakContext(ctx()).getBuiltins(); + var typesToSkip = List.of(builtins.function(), builtins.dataflowError(), builtins.warning()); + var shouldBeSkipped = typesToSkip.stream().anyMatch(toSkip -> toSkip == type); + return shouldBeSkipped; + } + + public record ValueWithType(Value value, Type type) {} } From 7f0d4bf747621061a302f57a97e619210e911f5f Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Fri, 29 Nov 2024 17:24:29 +0100 Subject: [PATCH 04/44] Add TypesExposeConstructorsTest --- .../interop/TypesExposeConstructorsTest.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/interop/TypesExposeConstructorsTest.java diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/interop/TypesExposeConstructorsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/interop/TypesExposeConstructorsTest.java new file mode 100644 index 000000000000..4e2bad1c3ef4 --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/interop/TypesExposeConstructorsTest.java @@ -0,0 +1,101 @@ +package org.enso.interpreter.test.interop; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.util.ArrayList; +import java.util.Objects; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.test.ValuesGenerator; +import org.enso.interpreter.test.ValuesGenerator.Language; +import org.enso.test.utils.ContextUtils; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests that every {@link org.enso.interpreter.runtime.data.Type} exposes its constructors as + * {@link com.oracle.truffle.api.interop.InteropLibrary#getMembers(Object) members}, and that such + * members are {@link com.oracle.truffle.api.interop.InteropLibrary#isInstantiable(Object) + * instantiable}. + */ +@RunWith(Parameterized.class) +public class TypesExposeConstructorsTest { + private static Context ctx; + + private final TypeWithWrapper typeWithWrapper; + + public TypesExposeConstructorsTest(TypeWithWrapper typeWithWrapper) { + this.typeWithWrapper = typeWithWrapper; + } + + private static Context ctx() { + if (ctx == null) { + ctx = ContextUtils.createDefaultContext(); + } + return ctx; + } + + @AfterClass + public static void disposeCtx() { + if (ctx != null) { + ctx.close(); + ctx = null; + } + } + + @Parameters(name = "{index}: {0}") + public static Iterable collectTypes() { + var collectedTypes = new ArrayList(); + ContextUtils.executeInContext( + ctx(), + () -> { + var valuesGenerator = ValuesGenerator.create(ctx(), Language.ENSO); + valuesGenerator.allTypes().stream() + .map( + tp -> { + var unwrappedTp = ContextUtils.unwrapValue(ctx(), tp); + if (unwrappedTp instanceof Type type) { + return new TypeWithWrapper(type, tp); + } else { + return null; + } + }) + .filter(Objects::nonNull) + .filter(tp -> !tp.type.getConstructors().isEmpty()) + .forEach(collectedTypes::add); + return null; + }); + return collectedTypes; + } + + @Test + public void typesExposeConstructorsAsMembers() { + var type = typeWithWrapper.type; + var typeValue = typeWithWrapper.typeValue; + var consNames = type.getConstructors().keySet(); + for (var consName : consNames) { + assertThat( + "Constructor " + consName + " should be exposed as a member", + typeValue.hasMember(consName), + is(true)); + var consMember = typeValue.getMember(consName); + assertThat(consMember, is(notNullValue())); + assertThat( + "Constructor " + consName + " should be instantiable", + consMember.canInstantiate(), + is(true)); + } + } + + /** + * @param type + * @param typeValue The polyglot value of the type (not an object) + */ + public record TypeWithWrapper(Type type, Value typeValue) {} +} From 48005e62dbab2536509c435ca092ee4aa6664151 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 12:49:49 +0100 Subject: [PATCH 05/44] Naive implementation of BuiltinObject base class. --- .../expression/builtin/BuiltinObject.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java new file mode 100644 index 000000000000..28394741d8cb --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java @@ -0,0 +1,139 @@ +package org.enso.interpreter.node.expression.builtin; + +import com.oracle.truffle.api.dsl.Bind; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.Node; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +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.data.EnsoObject; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; +import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; + +/** + * Base class for every Enso builtin object. Not type. Note that base class for a builtin type is + * {@link Builtin}. TODO: BuiltinTypeProcessor should ensure that all the builtin types are + * subclasses of BuiltinObject. + * + *

The {@link InteropLibrary interop} protocol corresponds to the implementation of the protocol + * inside {@link org.enso.interpreter.runtime.data.atom.Atom}. + */ +@ExportLibrary(InteropLibrary.class) +@ExportLibrary(TypesLibrary.class) +public abstract class BuiltinObject extends EnsoObject { + + private final String builtinName; + private Map methods; + + protected BuiltinObject(String builtinName) { + this.builtinName = builtinName; + } + + @ExportMessage + public boolean hasMembers() { + return true; + } + + @ExportMessage + public Object getMembers(boolean includeInternal, @Bind("$node") Node node) { + var ctx = EnsoContext.get(node); + var methodNamesArr = methodNames(ctx).toArray(String[]::new); + return ArrayLikeHelpers.wrapStrings(methodNamesArr); + } + + @ExportMessage + public boolean isMemberReadable(String member) { + var ctx = EnsoContext.get(null); + return methodNames(ctx).contains(member); + } + + @ExportMessage + public boolean isMemberInvocable(String member) { + return isMemberReadable(member); + } + + @ExportMessage + public Object readMember(String member) throws UnknownIdentifierException { + if (!isMemberReadable(member)) { + throw UnknownIdentifierException.create(member); + } + var ctx = EnsoContext.get(null); + var func = methods(ctx).get(member); + if (func != null) { + return func; + } + throw UnknownIdentifierException.create(member); + } + + @ExportMessage + public Object invokeMember(String member, Object[] args) + throws UnsupportedMessageException, UnsupportedTypeException, ArityException { + var ctx = EnsoContext.get(null); + var func = methods(ctx).get(member); + var sym = UnresolvedSymbol.build(member, ctx.getBuiltins().getScope()); + var argsForBuiltin = new Object[args.length + 1]; + argsForBuiltin[0] = this; + System.arraycopy(args, 0, argsForBuiltin, 1, args.length); + var interop = InteropLibrary.getUncached(); + return interop.execute(sym, argsForBuiltin); + } + + @ExportMessage + public boolean hasType() { + return true; + } + + @ExportMessage + public Type getType() { + var ctx = EnsoContext.get(null); + return ctx.getBuiltins().getBuiltinType(builtinName).getType(); + } + + @ExportMessage + public boolean hasMetaObject() { + return true; + } + + @ExportMessage + public Type getMetaObject() { + return getType(); + } + + private Map methods(EnsoContext ctx) { + if (methods == null) { + var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); + var defScope = builtinType.getType().getDefinitionScope(); + var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); + // TODO: If null the methods is empty set + assert methodsFromScope != null; + methods = new HashMap<>(); + for (var m : methodsFromScope) { + methods.put(m.getName(), m); + } + } + return methods; + } + + private Set methodNames(EnsoContext ctx) { + var methodNames = + methods(ctx).keySet().stream() + .map( + funcName -> { + var funcNameItems = funcName.split("\\."); + return funcNameItems[funcNameItems.length - 1]; + }) + .collect(Collectors.toUnmodifiableSet()); + return methodNames; + } +} From 477de23d390d6990d20c80d621ca2398765e6480 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 12:49:58 +0100 Subject: [PATCH 06/44] Ref extends BuiltinObject --- .../enso/interpreter/runtime/data/Ref.java | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java index e9e1728cacc0..eb74b1ba4980 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java @@ -1,21 +1,17 @@ package org.enso.interpreter.runtime.data; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; /** A mutable reference type. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "mutable", stdlibName = "Standard.Base.Runtime.Ref.Ref") -public final class Ref extends EnsoObject { +public final class Ref extends BuiltinObject { private volatile Object value; /** @@ -25,6 +21,7 @@ public final class Ref extends EnsoObject { */ @Builtin.Method(description = "Creates a new Ref", autoRegister = false) public Ref(Object value) { + super("Ref"); this.value = value; } @@ -51,26 +48,6 @@ public Object setValue(Object value) { return old; } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().ref(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().ref(); - } - @ExportMessage Object toDisplayString( boolean allowSideEffects, @CachedLibrary(limit = "3") InteropLibrary interop) { From 86c360b794b5037140364cfed95f283c53fd7eae Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 13:07:03 +0100 Subject: [PATCH 07/44] Builtin type anot processor ensures that a class must extend BuiltinObject --- .../interpreter/dsl/BuiltinsProcessor.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java index 17806a3d297d..8ea63ea0d112 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java @@ -90,6 +90,7 @@ public final boolean process(Set annotations, RoundEnviro */ public void handleClassElement(Element element, RoundEnvironment roundEnv) throws IOException { TypeElement elt = (TypeElement) element; + ensureBuiltinClassExtendsBuiltinObject(elt); Builtin annotation = element.getAnnotation(Builtin.class); String clazzName = annotation.name().isEmpty() ? element.getSimpleName().toString() : annotation.name(); @@ -347,6 +348,31 @@ private int specializationsCount(Element owner, String builtinMethodName) { .count(); } + /** + * @param builtinClass Class annotated with {@link Builtin}. + */ + private void ensureBuiltinClassExtendsBuiltinObject(TypeElement builtinClass) { + var builtinObjectBinName = "org.enso.interpreter.node.expression.builtin.BuiltinObject"; + if (!isSubtype(builtinClass, builtinObjectBinName)) { + processingEnv + .getMessager() + .printMessage( + Kind.ERROR, "Builtin class must extend " + builtinObjectBinName, builtinClass); + } + } + + /** + * Returns true if the given {@code clazz} is a subtype of class with binary name {@code + * binaryName}. + * + * @param clazz class to check + * @param binaryName binary name of the class to check against + */ + private boolean isSubtype(TypeElement clazz, String binaryName) { + var superType = processingEnv.getElementUtils().getTypeElement(binaryName); + return processingEnv.getTypeUtils().isSubtype(clazz.asType(), superType.asType()); + } + private final List typeNecessaryImports = Arrays.asList( "org.enso.interpreter.dsl.BuiltinType", From bac459e181e2653f299ce3e8ad03d05d1a382872 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 13:07:20 +0100 Subject: [PATCH 08/44] Enrich BuiltinsExposeMethodsTest --- .../test/builtins/BuiltinsExposeMethodsTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java index 63712d49ff0e..cd896663b5ee 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java @@ -87,6 +87,14 @@ public void builtinExposeMethods() { var items = methodName.split("\\."); methodName = items[items.length - 1]; } + assertThat( + "Builtin type " + valueWithType.type.getQualifiedName() + " should have members", + valueWithType.value.hasMembers(), + is(true)); + assertThat( + "Member " + methodName + " should be present", + valueWithType.value.hasMember(methodName), + is(true)); assertThat( "Member " + methodName + " should be invocable", valueWithType.value.canInvokeMember(methodName), From a9681e359f62e3aadd938b41c416bac71bd000c6 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:11:55 +0100 Subject: [PATCH 09/44] All builtin types extend BuiltinObject --- .../expression/builtin/BuiltinObject.java | 9 +++++ .../interpreter/runtime/data/EnsoDate.java | 28 ++------------ .../runtime/data/EnsoDateTime.java | 29 ++------------- .../runtime/data/EnsoDuration.java | 28 ++------------ .../interpreter/runtime/data/EnsoFile.java | 27 ++------------ .../runtime/data/EnsoTimeOfDay.java | 29 ++------------- .../runtime/data/EnsoTimeZone.java | 29 ++------------- .../runtime/data/ManagedResource.java | 28 ++------------ .../runtime/data/hash/EnsoHashMap.java | 30 ++------------- .../runtime/data/vector/Array.java | 30 ++------------- .../runtime/data/vector/ArrayLikeHelpers.java | 12 +++++- .../runtime/data/vector/Vector.java | 37 +++---------------- .../interpreter/runtime/warning/Warning.java | 20 ++-------- 13 files changed, 56 insertions(+), 280 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java index 28394741d8cb..081f79919fa5 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java @@ -37,6 +37,7 @@ public abstract class BuiltinObject extends EnsoObject { private Map methods; protected BuiltinObject(String builtinName) { + assert assertBuiltinDefined(builtinName); this.builtinName = builtinName; } @@ -136,4 +137,12 @@ private Set methodNames(EnsoContext ctx) { .collect(Collectors.toUnmodifiableSet()); return methodNames; } + + private static boolean assertBuiltinDefined(String builtinName) { + var builtinType = EnsoContext.get(null).getBuiltins().getBuiltinType(builtinName); + if (builtinType == null) { + throw new AssertionError("Builtin type " + builtinName + " is not defined"); + } + return true; + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java index 87d54ad80b7b..cb9cb8951a9f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java @@ -1,27 +1,25 @@ package org.enso.interpreter.runtime.data; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalTime; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "date", name = "Date", stdlibName = "Standard.Base.Data.Time.Date.Date") -public final class EnsoDate extends EnsoObject { +public final class EnsoDate extends BuiltinObject { private final LocalDate date; public EnsoDate(LocalDate date) { + super("Date"); this.date = date; } @@ -77,26 +75,6 @@ LocalTime asTime() throws UnsupportedMessageException { throw UnsupportedMessageException.create(); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().date(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().date(); - } - @CompilerDirectives.TruffleBoundary @ExportMessage @Override diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java index 637626e3c938..27643b6e679e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java @@ -1,34 +1,31 @@ package org.enso.interpreter.runtime.data; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin( pkg = "date", name = "DateTime", stdlibName = "Standard.Base.Data.Time.Date_Time.Date_Time") -public final class EnsoDateTime extends EnsoObject { +public final class EnsoDateTime extends BuiltinObject { private final ZonedDateTime dateTime; public EnsoDateTime(ZonedDateTime dateTime) { + super("Date_Time"); this.dateTime = dateTime; } @@ -205,26 +202,6 @@ ZoneId asTimeZone() { return dateTime.getZone(); } - @ExportMessage - Type getMetaObject(@CachedLibrary("this") InteropLibrary thisLib) { - return EnsoContext.get(thisLib).getBuiltins().dateTime(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().dateTime(); - } - @ExportMessage @CompilerDirectives.TruffleBoundary @Override diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java index ef441702d61e..1408aea59fa7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java @@ -1,12 +1,10 @@ package org.enso.interpreter.runtime.data; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -15,40 +13,20 @@ import java.time.ZonedDateTime; import java.time.temporal.Temporal; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.error.PanicException; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "date", name = "Duration", stdlibName = "Standard.Base.Data.Time.Duration.Duration") -public final class EnsoDuration extends EnsoObject { +public final class EnsoDuration extends BuiltinObject { private final Duration duration; public EnsoDuration(Duration duration) { + super("Duration"); this.duration = duration; } - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().duration(); - } - - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().duration(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - @Builtin.Method( name = "new_builtin", description = diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java index c99a6e067370..dd06275e5dd8 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java @@ -3,7 +3,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -37,6 +36,7 @@ import java.util.Set; import java.util.function.Function; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.data.vector.ArrayLikeAtNode; @@ -44,19 +44,18 @@ import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode; import org.enso.interpreter.runtime.error.DataflowError; import org.enso.interpreter.runtime.error.PanicException; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** * A wrapper for {@link TruffleFile} objects exposed to the language. For methods documentation * please refer to {@link TruffleFile}. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "io", name = "File", stdlibName = "Standard.Base.System.File.File") -public final class EnsoFile extends EnsoObject { +public final class EnsoFile extends BuiltinObject { private final TruffleFile truffleFile; public EnsoFile(TruffleFile truffleFile) { + super("File"); if (truffleFile == null) { throw CompilerDirectives.shouldNotReachHere(); } @@ -797,26 +796,6 @@ public String toString() { return toDisplayString(false); } - @ExportMessage - Type getMetaObject(@CachedLibrary("this") InteropLibrary thisLib) { - return EnsoContext.get(thisLib).getBuiltins().file(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().file(); - } - static RuntimeException raiseIOException(Node where, IOException ex) { var ctx = EnsoContext.get(where); var guestEx = ctx.asGuestValue(ex); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java index 29da641fe54c..62b24c0ef404 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java @@ -2,31 +2,28 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin( pkg = "date", name = "TimeOfDay", stdlibName = "Standard.Base.Data.Time.Time_Of_Day.Time_Of_Day") -public final class EnsoTimeOfDay extends EnsoObject { +public final class EnsoTimeOfDay extends BuiltinObject { private final LocalTime localTime; public EnsoTimeOfDay(LocalTime localTime) { + super("Time_Of_Day"); this.localTime = localTime; } @@ -143,26 +140,6 @@ LocalDate asDate() throws UnsupportedMessageException { throw UnsupportedMessageException.create(); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().timeOfDay(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().timeOfDay(); - } - @CompilerDirectives.TruffleBoundary @ExportMessage @Override diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java index 3f9da89a3797..5f5b5f2d4e8c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java @@ -2,32 +2,29 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.time.DateTimeException; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.zone.ZoneRulesException; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin( pkg = "date", name = "TimeZone", stdlibName = "Standard.Base.Data.Time.Time_Zone.Time_Zone") -public final class EnsoTimeZone extends EnsoObject { +public final class EnsoTimeZone extends BuiltinObject { private final ZoneId zone; public EnsoTimeZone(ZoneId zone) { + super("Time_Zone"); this.zone = zone; } @@ -100,24 +97,4 @@ boolean isTimeZone() { ZoneId asTimeZone() { return zone; } - - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().timeZone(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().timeZone(); - } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java index e931f8bf01f7..5ac55b5569f8 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java @@ -9,9 +9,9 @@ import com.oracle.truffle.api.nodes.Node; import java.lang.ref.PhantomReference; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** * An Enso runtime representation of a managed resource. @@ -35,9 +35,8 @@ * ProcessItems} processor. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "resource", stdlibName = "Standard.Base.Runtime.Managed_Resource.Managed_Resource") -public final class ManagedResource extends EnsoObject { +public final class ManagedResource extends BuiltinObject { private final Object resource; private final PhantomReference phantomReference; @@ -50,6 +49,7 @@ public final class ManagedResource extends EnsoObject { public ManagedResource( Object resource, java.util.function.Function> factory) { + super("Managed_Resource"); this.resource = resource; this.phantomReference = factory.apply(this); } @@ -97,30 +97,10 @@ public void close(EnsoContext context) { context.getResourceManager().close(this); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().managedResource(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().managedResource(); - } - @ExportMessage @TruffleBoundary public String toDisplayString(boolean allowSideEffects, @Bind("$node") Node node) { - var type = getType(node); + var type = getType(); return type.getName() + " " + InteropLibrary.getUncached().toDisplayString(resource, allowSideEffects); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java index 65261cebf96e..e71ce7fa1092 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java @@ -1,7 +1,6 @@ package org.enso.interpreter.runtime.data.hash; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.frame.VirtualFrame; @@ -11,17 +10,14 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.builtin.meta.EqualsNode; import org.enso.interpreter.node.expression.builtin.meta.HashCodeNode; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.hash.EnsoHashMapBuilder.StorageEntry; import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** * Implementation of a hash map structure, capable of holding any types of keys and values. The @@ -33,10 +29,9 @@ *

Users should not use Enso objects as keys to Java maps, because equals won't work the same way * as it works in Enso. */ -@ExportLibrary(TypesLibrary.class) @ExportLibrary(InteropLibrary.class) @Builtin(stdlibName = "Standard.Base.Data.Dictionary.Dictionary", name = "Dictionary") -public final class EnsoHashMap extends EnsoObject { +public final class EnsoHashMap extends BuiltinObject { private final EnsoHashMapBuilder mapBuilder; private final int generation; private final int size; @@ -44,6 +39,7 @@ public final class EnsoHashMap extends EnsoObject { private Object cachedVectorRepresentation; private EnsoHashMap(EnsoHashMapBuilder mapBuilder) { + super("Dictionary"); this.mapBuilder = mapBuilder; this.generation = mapBuilder.generation(); this.size = mapBuilder.size(); @@ -144,26 +140,6 @@ Object getHashEntriesIterator(@CachedLibrary(limit = "3") InteropLibrary interop } } - @ExportMessage(library = TypesLibrary.class) - boolean hasType() { - return true; - } - - @ExportMessage(library = TypesLibrary.class) - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().dictionary(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().dictionary(); - } - @ExportMessage @TruffleBoundary @Override diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java index d70ad6b44fda..c96cf4dc90f0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java @@ -2,7 +2,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.interop.InteropLibrary; @@ -11,29 +10,25 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import java.util.Arrays; import java.util.Comparator; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.hash.HashMapInsertAllNode; import org.enso.interpreter.runtime.data.hash.HashMapInsertNode; import org.enso.interpreter.runtime.data.hash.HashMapSizeNode; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.warning.AppendWarningNode; import org.enso.interpreter.runtime.warning.Warning; import org.enso.interpreter.runtime.warning.WarningsLibrary; /** A primitive boxed array type for use in the runtime. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @ExportLibrary(WarningsLibrary.class) @Builtin(pkg = "mutable", stdlibName = "Standard.Base.Data.Array.Array") -final class Array extends EnsoObject { +final class Array extends BuiltinObject { private final Object[] items; /** If true, some elements contain warning, and thus, this Array contains warning. */ @@ -49,6 +44,7 @@ final class Array extends EnsoObject { * @param items the element values */ private Array(Object... items) { + super("Array"); this.items = items; } @@ -159,27 +155,12 @@ public String toDisplayString(boolean b) { return toString(); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().array(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - @Override @CompilerDirectives.TruffleBoundary public String toString() { return Arrays.toString(items); } - @ExportMessage - boolean hasType() { - return true; - } - private boolean hasWarningElements(Object[] items, WarningsLibrary warnings) { for (Object item : items) { if (warnings.hasWarnings(item)) { @@ -306,9 +287,4 @@ boolean isLimitReached( return false; } } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().array(); - } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java index 75255bb9abd9..ea2cee7a0e33 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java @@ -5,12 +5,15 @@ import com.oracle.truffle.api.library.CachedLibrary; import java.nio.ByteBuffer; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.EnsoObject; /** Publicly available operations on array-like classes. */ @Builtin(pkg = "immutable", stdlibName = "Standard.Base.Internal.Array_Like_Helpers") -public final class ArrayLikeHelpers { - private ArrayLikeHelpers() {} +public final class ArrayLikeHelpers extends BuiltinObject { + private ArrayLikeHelpers() { + super("Array_Like_Helpers"); + } @Builtin.Method( name = "new_array_proxy_builtin", @@ -121,4 +124,9 @@ public static EnsoObject asVectorEnsoObjects(EnsoObject... arr) { public static EnsoObject asVectorEmpty() { return Vector.fromEnsoOnlyArray(null); } + + @Override + public Object toDisplayString(boolean allowSideEffects) { + return "Array_Like_Helpers"; + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java index 9893427ad676..a82d8166cf80 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java @@ -1,7 +1,6 @@ package org.enso.interpreter.runtime.data.vector; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; @@ -9,25 +8,25 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.foreign.HostValueToEnsoNode; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.warning.AppendWarningNode; import org.enso.interpreter.runtime.warning.WarningsLibrary; @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector") -abstract class Vector extends EnsoObject { +abstract class Vector extends BuiltinObject { private static final Vector EMPTY_LONG = new Long(new long[0]); private static final Vector EMPTY_DOUBLE = new Double(new double[0]); private static final Vector EMPTY_VECTOR = new EnsoOnly(new Object[0]); + protected Vector() { + super("Vector"); + } + @ExportMessage boolean hasArrayElements() { return true; @@ -78,30 +77,6 @@ public String toDisplayString(boolean allowSideEffects) { return DisplayArrayUtils.toDisplayString(this, allowSideEffects, iop); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().vector(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - // - // methods for TypesLibrary - // - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().vector(); - } - // // helper methods // diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java index 27096e7881f5..c31934f4012b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java @@ -2,31 +2,27 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.StopIterationException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.hash.HashMapInsertNode; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; @Builtin(pkg = "error", stdlibName = "Standard.Base.Warning.Warning") -@ExportLibrary(TypesLibrary.class) @ExportLibrary(value = InteropLibrary.class, delegateTo = "value") -public final class Warning extends EnsoObject { +public final class Warning extends BuiltinObject { final Object value; private final Object origin; private final long sequenceId; private Warning(Object value, Object origin, long sequenceId) { + super("Warning"); this.value = value; this.origin = origin; this.sequenceId = sequenceId; @@ -129,16 +125,6 @@ public long getSequenceId() { return sequenceId; } - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().warning(); - } - public static Warning wrapMapError(WarningsLibrary warningsLib, Warning warning, long index) { var ctx = EnsoContext.get(warningsLib); var error = warning.getValue(); From ab7a246fc386b43c01083eb7328f147450a99ea9 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:39:34 +0100 Subject: [PATCH 10/44] Text is BuiltinObject --- .../interpreter/runtime/data/text/Text.java | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java index 7ae2fac6fbc1..17bc028a1aed 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java @@ -2,12 +2,10 @@ import com.ibm.icu.text.Normalizer2; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.api.strings.TruffleString.Encoding; import java.util.ArrayDeque; @@ -15,17 +13,13 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Text_Utils; /** The main runtime type for Enso's Text. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) -public final class Text extends EnsoObject { +public final class Text extends BuiltinObject { private static final Lock LOCK = new ReentrantLock(); private static final Text EMPTY = new Text(""); private volatile Object contents; @@ -39,10 +33,12 @@ private enum FcdNormalized { } private Text(String string) { + super("Text"); this.contents = string; } private Text(ConcatRope contents) { + super("Text"); this.contents = contents; } @@ -212,16 +208,6 @@ String toDisplayString( return Core_Text_Utils.prettyPrint(str); } - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().text(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - private void setContents(String contents) { assert length == -1 || length == contents.length(); this.contents = contents; @@ -245,16 +231,6 @@ public String toString() { } } - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().text(); - } - /** * Converts text to a Java String. For use outside of Truffle Nodes. * From 4c9ea78acd081d81db25d44e1ac1402bf70bf1fc Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:39:50 +0100 Subject: [PATCH 11/44] EnsoBigInteger is BuiltinObject --- .../runtime/number/EnsoBigInteger.java | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java index 961d31e88027..8f10990bf0ec 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java @@ -1,23 +1,16 @@ package org.enso.interpreter.runtime.number; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import java.math.BigInteger; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; /** Internal wrapper for a {@link BigInteger}. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) -public final class EnsoBigInteger extends EnsoObject { +public final class EnsoBigInteger extends BuiltinObject { private final BigInteger value; /** @@ -26,6 +19,7 @@ public final class EnsoBigInteger extends EnsoObject { * @param value the value to wrap. */ public EnsoBigInteger(BigInteger value) { + super("Integer"); assert (value.bitLength() > 63) : "Too small BigInteger: " + value; this.value = value; } @@ -125,26 +119,6 @@ public final BigInteger asBigInteger() { return value; } - @ExportMessage - Type getMetaObject(@CachedLibrary("this") InteropLibrary thisLib) { - return EnsoContext.get(thisLib).getBuiltins().number().getInteger(); - } - - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().number().getInteger(); - } - @Override public boolean equals(Object obj) { if (obj instanceof EnsoBigInteger otherBigInt) { From e806f9f46ed7456c04614e41a31c5eb57cb6e469 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:40:10 +0100 Subject: [PATCH 12/44] BuiltinObject does no asserts in constructor --- .../node/expression/builtin/BuiltinObject.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java index 081f79919fa5..6d9ee837cf53 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java @@ -37,7 +37,6 @@ public abstract class BuiltinObject extends EnsoObject { private Map methods; protected BuiltinObject(String builtinName) { - assert assertBuiltinDefined(builtinName); this.builtinName = builtinName; } @@ -114,6 +113,7 @@ public Type getMetaObject() { private Map methods(EnsoContext ctx) { if (methods == null) { var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); + assert builtinType != null; var defScope = builtinType.getType().getDefinitionScope(); var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); // TODO: If null the methods is empty set @@ -137,12 +137,4 @@ private Set methodNames(EnsoContext ctx) { .collect(Collectors.toUnmodifiableSet()); return methodNames; } - - private static boolean assertBuiltinDefined(String builtinName) { - var builtinType = EnsoContext.get(null).getBuiltins().getBuiltinType(builtinName); - if (builtinType == null) { - throw new AssertionError("Builtin type " + builtinName + " is not defined"); - } - return true; - } } From 3b98c6028178508324b01317f7ee1aa4f2eaf0e8 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:40:21 +0100 Subject: [PATCH 13/44] ArrayProxy is BuiltinObject --- .../runtime/data/vector/ArrayProxy.java | 31 ++----------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java index 0aca184e7e45..6c89f4e8df88 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java @@ -2,7 +2,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.interop.ArityException; @@ -13,12 +12,8 @@ import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; +import org.enso.interpreter.node.expression.builtin.BuiltinObject; /** * A wrapper that allows to turn an Enso callback providing elements into a polyglot Array. @@ -27,13 +22,13 @@ * example exposing rows of a Table without copying any data. */ @ExportLibrary(InteropLibrary.class) -@ExportLibrary(TypesLibrary.class) @ImportStatic(BranchProfile.class) -final class ArrayProxy extends EnsoObject { +final class ArrayProxy extends BuiltinObject { private final long length; private final Object at; private ArrayProxy(long length, Object at) { + super("Array"); assert length >= 0; assert InteropLibrary.getUncached().isExecutable(at); this.length = length; @@ -83,29 +78,9 @@ public String toDisplayString(boolean b) { return toString(); } - @ExportMessage - boolean hasMetaObject() { - return true; - } - - @ExportMessage - Type getMetaObject(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().array(); - } - @Override @CompilerDirectives.TruffleBoundary public String toString() { return "(Array_Proxy " + length + " " + at + ")"; } - - @ExportMessage - boolean hasType() { - return true; - } - - @ExportMessage - Type getType(@Bind("$node") Node node) { - return EnsoContext.get(node).getBuiltins().array(); - } } From 643aa36d0c69d9a550730a5e7fe2fdc731d618ce Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:40:37 +0100 Subject: [PATCH 14/44] Test skips host values and Nothing --- .../test/builtins/BuiltinsExposeMethodsTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java index cd896663b5ee..db5f725a080c 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java @@ -52,6 +52,7 @@ public static Iterable generateBuiltinObjects() { .map(val -> new ValueWithType(val, getType(val))) .filter(valWithType -> !shouldSkipType(valWithType.type)) .filter(valWithType -> !isPrimitive(valWithType.value)) + .filter(valWithType -> !isHostValue(valWithType.value)) .forEach(builtinObjectsWithTypes::add); return null; }); @@ -121,10 +122,18 @@ private static boolean shouldSkipType(Type type) { return true; } var builtins = ContextUtils.leakContext(ctx()).getBuiltins(); - var typesToSkip = List.of(builtins.function(), builtins.dataflowError(), builtins.warning()); + var typesToSkip = + List.of( + builtins.function(), builtins.dataflowError(), builtins.warning(), builtins.nothing()); var shouldBeSkipped = typesToSkip.stream().anyMatch(toSkip -> toSkip == type); return shouldBeSkipped; } + private static boolean isHostValue(Value value) { + var unwrapped = ContextUtils.unwrapValue(ctx(), value); + var ensoCtx = ContextUtils.leakContext(ctx()); + return ensoCtx.isJavaPolyglotObject(unwrapped); + } + public record ValueWithType(Value value, Type type) {} } From 5a8ef4eb784b401a230e361542d0bcb0da6dcbcf Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:40:42 +0100 Subject: [PATCH 15/44] fmt --- .../main/java/org/enso/interpreter/runtime/data/EnsoDate.java | 1 - .../java/org/enso/interpreter/runtime/data/EnsoDateTime.java | 1 - 2 files changed, 2 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java index cb9cb8951a9f..5a4c655d290a 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java @@ -10,7 +10,6 @@ import java.time.LocalTime; import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.node.expression.builtin.BuiltinObject; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java index 27643b6e679e..c898627900aa 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java @@ -13,7 +13,6 @@ import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) From 7cd64693fac05569b6dd3f6c79f06529a4b86a46 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 18:50:56 +0100 Subject: [PATCH 16/44] Remove outdated test. No longer true what this test tested --- .../interpreter/test/semantic/PolyglotTest.scala | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/PolyglotTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/PolyglotTest.scala index c0f8463a0b21..85a2ab2917b4 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/PolyglotTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/PolyglotTest.scala @@ -92,20 +92,6 @@ class PolyglotTest extends InterpreterTest { ) } - "empty members when message not supported" in { - val code = - """from Standard.Base import all - | - |main = - | instance = "Hi There" - | members = Polyglot.get_members instance - | IO.println members.length - | IO.println members - |""".stripMargin - eval(code) - consumeOut shouldEqual List("0", "[]") - } - "fail to match on Polyglot symbol when imported everything from stdlib" in { val code = """from Standard.Base import all From 475819aab1b5522a62c344958afcfa859ae5a90a Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:13:59 +0100 Subject: [PATCH 17/44] EqualsComplexNode: Timezone and duration are not treated as object with members --- .../node/expression/builtin/meta/EqualsComplexNode.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java index d742b45f646c..20ee96d276eb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java @@ -543,6 +543,12 @@ boolean isObjectWithMembers(Object object, InteropLibrary interop) { if (interop.isTime(object)) { return false; } + if (interop.isDuration(object)) { + return false; + } + if (interop.isTimeZone(object)) { + return false; + } if (interop.hasHashEntries(object)) { return false; } From 78563246f5fc724d103e930d7821f263071c957f Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:14:21 +0100 Subject: [PATCH 18/44] Fix DebuggingEnsoTest - Date in js is date time, not date --- .../java/org/enso/interpreter/test/DebuggingEnsoTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java index f10b10c34598..a953212fade7 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java @@ -307,10 +307,10 @@ public void hostValueIsTreatedAsItsEnsoCounterpart() { foo _ = d_enso = Date.new 2024 12 15 - d_js = js_date d_java = Date.parse "2024-12-15" dt_enso = Date_Time.now dt_java = Date_Time.parse "2020-05-06 04:30:20" "yyyy-MM-dd HH:mm:ss" + dt_js = js_date str_enso = "Hello_World" str_js = js_str str_java = String.new "Hello_World" @@ -335,13 +335,13 @@ public void hostValueIsTreatedAsItsEnsoCounterpart() { DebugValue ensoDate = scope.getDeclaredValue("d_enso"); DebugValue javaDate = scope.getDeclaredValue("d_java"); - DebugValue jsDate = scope.getDeclaredValue("d_js"); assertSameProperties(ensoDate.getProperties(), javaDate.getProperties()); - assertSameProperties(ensoDate.getProperties(), jsDate.getProperties()); DebugValue ensoDateTime = scope.getDeclaredValue("dt_enso"); DebugValue javaDateTime = scope.getDeclaredValue("dt_java"); + DebugValue jsDateTime = scope.getDeclaredValue("dt_js"); assertSameProperties(ensoDateTime.getProperties(), javaDateTime.getProperties()); + assertSameProperties(ensoDateTime.getProperties(), jsDateTime.getProperties()); DebugValue ensoString = scope.getDeclaredValue("str_enso"); DebugValue javaString = scope.getDeclaredValue("str_java"); From a00ef609fc89f4e0c681b7d3a1a80064753e17d5 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:14:37 +0100 Subject: [PATCH 19/44] Fix DateTest - ensoDate now has members --- .../scala/org/enso/interpreter/test/semantic/DateTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DateTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DateTest.scala index c2bde01b4b7a..04e904bab0c1 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DateTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DateTest.scala @@ -73,7 +73,7 @@ class DateTest extends InterpreterTest { |""".stripMargin val ensoDate = eval(code) consumeOut shouldEqual List("2022", "4", "1", "2022-04-01") - ensoDate.getMemberKeys().size() shouldEqual 0 + ensoDate.getMemberKeys().size() shouldNot be(0) } } } From 0658ca50eb618b2179c30d0af8a0ee3e1b797f7b Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:14:59 +0100 Subject: [PATCH 20/44] Add interop.readMember test to BuiltinsExposeMethodsTest --- .../test/builtins/BuiltinsExposeMethodsTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java index db5f725a080c..db547df94d7e 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java @@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import com.oracle.truffle.api.interop.InteropLibrary; import java.util.ArrayList; import java.util.List; import org.enso.interpreter.runtime.data.Type; @@ -100,6 +101,13 @@ public void builtinExposeMethods() { "Member " + methodName + " should be invocable", valueWithType.value.canInvokeMember(methodName), is(true)); + var interop = InteropLibrary.getUncached(); + var unwrappedValue = ContextUtils.unwrapValue(ctx(), valueWithType.value); + var memberViaInterop = interop.readMember(unwrappedValue, methodName); + assertThat( + "Member via interop should be the same as in scope, but was: " + memberViaInterop, + memberViaInterop == methodInScope, + is(true)); } } return null; From c1d8f412cace7e76eb44760f28296fcbf3135405 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:15:27 +0100 Subject: [PATCH 21/44] VectorSortTest is executed in context --- .../enso/interpreter/test/VectorSortTest.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/VectorSortTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/VectorSortTest.java index d8a6c8b7498e..e6259b7de62a 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/VectorSortTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/VectorSortTest.java @@ -61,18 +61,23 @@ public static void disposeCtx() { @Theory public void testSortHandlesAllValues(Value value1, Value value2) { - Assume.assumeFalse(isNan(value1) || isNan(value2)); - Value res = sortFunc.execute(value1, value2); - assertTrue(res.hasArrayElements()); - assertEquals(2, res.getArraySize()); - List resArray = readPolyglotArray(res); - // check that value1 is there unchanged on some index, and the same for value2 - assertTrue( - "Sorted vector should contain the first value at any index", - invokeEquals(value1, resArray.get(0)) || invokeEquals(value1, resArray.get(1))); - assertTrue( - "Sorted vector should contain the second value at any index", - invokeEquals(value2, resArray.get(0)) || invokeEquals(value2, resArray.get(1))); + ContextUtils.executeInContext( + context, + () -> { + Assume.assumeFalse(isNan(value1) || isNan(value2)); + Value res = sortFunc.execute(value1, value2); + assertTrue(res.hasArrayElements()); + assertEquals(2, res.getArraySize()); + List resArray = readPolyglotArray(res); + // check that value1 is there unchanged on some index, and the same for value2 + assertTrue( + "Sorted vector should contain the first value at any index", + invokeEquals(value1, resArray.get(0)) || invokeEquals(value1, resArray.get(1))); + assertTrue( + "Sorted vector should contain the second value at any index", + invokeEquals(value2, resArray.get(0)) || invokeEquals(value2, resArray.get(1))); + return null; + }); } private boolean isNan(Value value) { From 47125a7f1a5e7654f8a65b7121f598bb32025043 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:33:42 +0100 Subject: [PATCH 22/44] Add tests that invoke builtin methods on particular builtin types --- .../InvokeBuiltinMethodViaInteropTest.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java new file mode 100644 index 000000000000..6f01bf18e2a5 --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java @@ -0,0 +1,120 @@ +package org.enso.interpreter.test.builtins; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import com.oracle.truffle.api.interop.InteropLibrary; +import org.enso.test.utils.ContextUtils; +import org.graalvm.polyglot.Context; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * This test tries to invoke some builtin methods on builtin types via the {@link + * com.oracle.truffle.api.interop.InteropLibrary interop} protocol. + */ +public class InvokeBuiltinMethodViaInteropTest { + private static Context ctx; + + @BeforeClass + public static void setUp() { + ctx = ContextUtils.createDefaultContext(); + } + + @AfterClass + public static void tearDown() { + ctx.close(); + ctx = null; + } + + @Test + public void invokeGetMethodOnRef() { + var code = + """ + import Standard.Base.Runtime.Ref.Ref + + main = Ref.new 42 + """; + var ref = ContextUtils.evalModule(ctx, code); + ContextUtils.executeInContext( + ctx, + () -> { + var interop = InteropLibrary.getUncached(); + var refUnwrapped = ContextUtils.unwrapValue(ctx, ref); + assertThat( + "Ref should have a 'get' method", + interop.isMemberInvocable(refUnwrapped, "get"), + is(true)); + var res = interop.invokeMember(refUnwrapped, "get"); + assertThat("Ref.get should return a number", interop.isNumber(res), is(true)); + assertThat("Ref.get should return 42", interop.asInt(res), is(42)); + return null; + }); + } + + /** + * 'Text.reverse' is an extension method defined outside builtins module scope, so it cannot be + * resolved. + */ + @Test + public void extensionMethodOnBuiltinTypeIsNotResolved() { + var text = ContextUtils.evalModule(ctx, "main = 'Hello'"); + ContextUtils.executeInContext( + ctx, + () -> { + var interop = InteropLibrary.getUncached(); + var textUnwrapped = ContextUtils.unwrapValue(ctx, text); + assertThat( + "Text should not be able to resolve 'reverse' method", + interop.isMemberInvocable(textUnwrapped, "reverse"), + is(false)); + return null; + }); + } + + @Test + public void invokePlusOnTextWithParameter() { + var text1 = ContextUtils.evalModule(ctx, "main = 'First'"); + var text2 = ContextUtils.evalModule(ctx, "main = 'Second'"); + ContextUtils.executeInContext( + ctx, + () -> { + var interop = InteropLibrary.getUncached(); + var text1Unwrapped = ContextUtils.unwrapValue(ctx, text1); + var text2Unwrapped = ContextUtils.unwrapValue(ctx, text2); + assertThat( + "Text should have a '+' method", + interop.isMemberInvocable(text1Unwrapped, "+"), + is(true)); + var res = interop.invokeMember(text1Unwrapped, "+", text2Unwrapped); + assertThat("Text.+ should return a text", interop.isString(res), is(true)); + assertThat( + "Text.+ should return 'FirstSecond'", interop.asString(res), is("FirstSecond")); + return null; + }); + } + + /** + * 'Text.is_empty' is not a builtin method, defined on a builtin type. It should be treated as a + * builtin method, thus be invocable via interop. + */ + @Test + public void invokeNonBuiltinMethodOnBuiltinType() { + var text = ContextUtils.evalModule(ctx, "main = 'Hello'"); + ContextUtils.executeInContext( + ctx, + () -> { + var interop = InteropLibrary.getUncached(); + var textUnwrapped = ContextUtils.unwrapValue(ctx, text); + assertThat( + "Text should have a 'is_empty' method", + interop.isMemberInvocable(textUnwrapped, "is_empty"), + is(true)); + var res = interop.invokeMember(textUnwrapped, "is_empty"); + assertThat("Text.is_empty should return a boolean", interop.isBoolean(res), is(true)); + assertThat("Text.is_empty should return false", interop.asBoolean(res), is(false)); + return null; + }); + } +} From e8ed818a9115991c1407a8445823d16092428318 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:35:45 +0100 Subject: [PATCH 23/44] member methods on BuiltinObject are behind TruffleBoundary --- .../expression/builtin/BuiltinObject.java | 58 ++++++++++--------- .../runtime/data/ManagedResource.java | 2 +- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java index 6d9ee837cf53..c00eb72b8c11 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java @@ -1,5 +1,6 @@ package org.enso.interpreter.node.expression.builtin; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -23,11 +24,13 @@ /** * Base class for every Enso builtin object. Not type. Note that base class for a builtin type is - * {@link Builtin}. TODO: BuiltinTypeProcessor should ensure that all the builtin types are - * subclasses of BuiltinObject. + * {@link Builtin}. * - *

The {@link InteropLibrary interop} protocol corresponds to the implementation of the protocol - * inside {@link org.enso.interpreter.runtime.data.atom.Atom}. + *

The {@link InteropLibrary interop} protocol roughly corresponds to the implementation of the + * protocol inside {@link org.enso.interpreter.runtime.data.atom.Atom}. + * + *

Note that extension methods are not resolved, because they are not defined in builtins module + * scope. In other words, extension methods are not reported as members via interop. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(TypesLibrary.class) @@ -46,30 +49,31 @@ public boolean hasMembers() { } @ExportMessage + @TruffleBoundary public Object getMembers(boolean includeInternal, @Bind("$node") Node node) { - var ctx = EnsoContext.get(node); - var methodNamesArr = methodNames(ctx).toArray(String[]::new); + var methodNamesArr = methodNames().toArray(String[]::new); return ArrayLikeHelpers.wrapStrings(methodNamesArr); } @ExportMessage + @TruffleBoundary public boolean isMemberReadable(String member) { - var ctx = EnsoContext.get(null); - return methodNames(ctx).contains(member); + return methodNames().contains(member); } @ExportMessage + @TruffleBoundary public boolean isMemberInvocable(String member) { return isMemberReadable(member); } @ExportMessage + @TruffleBoundary public Object readMember(String member) throws UnknownIdentifierException { if (!isMemberReadable(member)) { throw UnknownIdentifierException.create(member); } - var ctx = EnsoContext.get(null); - var func = methods(ctx).get(member); + var func = methods().get(member); if (func != null) { return func; } @@ -77,10 +81,10 @@ public Object readMember(String member) throws UnknownIdentifierException { } @ExportMessage + @TruffleBoundary public Object invokeMember(String member, Object[] args) throws UnsupportedMessageException, UnsupportedTypeException, ArityException { var ctx = EnsoContext.get(null); - var func = methods(ctx).get(member); var sym = UnresolvedSymbol.build(member, ctx.getBuiltins().getScope()); var argsForBuiltin = new Object[args.length + 1]; argsForBuiltin[0] = this; @@ -95,8 +99,8 @@ public boolean hasType() { } @ExportMessage - public Type getType() { - var ctx = EnsoContext.get(null); + public Type getType(@Bind("$node") Node node) { + var ctx = EnsoContext.get(node); return ctx.getBuiltins().getBuiltinType(builtinName).getType(); } @@ -106,35 +110,37 @@ public boolean hasMetaObject() { } @ExportMessage - public Type getMetaObject() { - return getType(); + public Type getMetaObject(@Bind("$node") Node node) { + return getType(node); } - private Map methods(EnsoContext ctx) { + private Map methods() { + var ctx = EnsoContext.get(null); if (methods == null) { var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); assert builtinType != null; var defScope = builtinType.getType().getDefinitionScope(); var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); - // TODO: If null the methods is empty set assert methodsFromScope != null; methods = new HashMap<>(); - for (var m : methodsFromScope) { - methods.put(m.getName(), m); + for (var method : methodsFromScope) { + var methodName = normalizeName(method.getName()); + methods.put(methodName, method); } } return methods; } - private Set methodNames(EnsoContext ctx) { + private Set methodNames() { var methodNames = - methods(ctx).keySet().stream() - .map( - funcName -> { - var funcNameItems = funcName.split("\\."); - return funcNameItems[funcNameItems.length - 1]; - }) + methods().keySet().stream() + .map(BuiltinObject::normalizeName) .collect(Collectors.toUnmodifiableSet()); return methodNames; } + + private static String normalizeName(String funcName) { + var funcNameItems = funcName.split("\\."); + return funcNameItems[funcNameItems.length - 1]; + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java index 5ac55b5569f8..ee817514c89c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java @@ -100,7 +100,7 @@ public void close(EnsoContext context) { @ExportMessage @TruffleBoundary public String toDisplayString(boolean allowSideEffects, @Bind("$node") Node node) { - var type = getType(); + var type = getType(node); return type.getName() + " " + InteropLibrary.getUncached().toDisplayString(resource, allowSideEffects); From 7dfb427356bd324f49f9e190b0b6d6916a2d557a Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 4 Dec 2024 20:56:47 +0100 Subject: [PATCH 24/44] Cache builtin type in BuiltinObject. This fixes native image build of engine-runner. --- .../node/expression/builtin/BuiltinObject.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java index c00eb72b8c11..402300a25e36 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java @@ -1,5 +1,6 @@ package org.enso.interpreter.node.expression.builtin; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.interop.ArityException; @@ -38,7 +39,12 @@ public abstract class BuiltinObject extends EnsoObject { private final String builtinName; private Map methods; + private Builtin cachedBuiltinType; + /** + * @param builtinName Simple name of the builtin that should be contained in {@link + * org.enso.interpreter.runtime.builtin.Builtins#builtinsByName}. + */ protected BuiltinObject(String builtinName) { this.builtinName = builtinName; } @@ -100,8 +106,12 @@ public boolean hasType() { @ExportMessage public Type getType(@Bind("$node") Node node) { - var ctx = EnsoContext.get(node); - return ctx.getBuiltins().getBuiltinType(builtinName).getType(); + if (cachedBuiltinType == null) { + CompilerDirectives.transferToInterpreter(); + var ctx = EnsoContext.get(node); + cachedBuiltinType = ctx.getBuiltins().getBuiltinType(builtinName); + } + return cachedBuiltinType.getType(); } @ExportMessage From 193db45bf1bcd71b2ff46c0b4dd937826fca9117 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 5 Dec 2024 12:39:06 +0100 Subject: [PATCH 25/44] Reuse context in DebuggingEnsoTest. This fixes the AssertionError in invalid sharing layer. --- .../interpreter/test/DebuggingEnsoTest.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java index a953212fade7..a2f15a0a3438 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java @@ -42,23 +42,23 @@ import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.io.IOAccess; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestWatcher; import org.junit.runner.Description; public class DebuggingEnsoTest { - private Context context; - private Engine engine; - private Debugger debugger; - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private static Context context; + private static Engine engine; + private static Debugger debugger; + private static final ByteArrayOutputStream out = new ByteArrayOutputStream(); - @Before - public void initContext() { - out.reset(); + @BeforeClass + public static void initContext() { engine = Engine.newBuilder() .allowExperimentalOptions(true) @@ -85,12 +85,18 @@ public void initContext() { Assert.assertNotNull("Enso found: " + langs, langs.get("enso")); } - @After - public void disposeContext() throws IOException { + @AfterClass + public static void disposeContext() throws IOException { context.close(); context = null; engine.close(); engine = null; + debugger = null; + } + + @Before + public void resetOut() { + out.reset(); } /** Only print warnings from the compiler if a test fails. */ From 8acb04a4f948ab28ea028c55e6035ea35256799e Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 12:19:39 +0100 Subject: [PATCH 26/44] Reuse hardcoded builtinName constants from annotation --- .../java/org/enso/interpreter/runtime/data/EnsoDate.java | 8 ++++++-- .../org/enso/interpreter/runtime/data/EnsoDateTime.java | 5 +++-- .../org/enso/interpreter/runtime/data/EnsoDuration.java | 8 ++++++-- .../java/org/enso/interpreter/runtime/data/EnsoFile.java | 5 +++-- .../org/enso/interpreter/runtime/data/EnsoTimeOfDay.java | 5 +++-- .../org/enso/interpreter/runtime/data/EnsoTimeZone.java | 5 +++-- .../enso/interpreter/runtime/data/ManagedResource.java | 8 ++++++-- .../main/java/org/enso/interpreter/runtime/data/Ref.java | 5 +++-- .../enso/interpreter/runtime/data/hash/EnsoHashMap.java | 5 +++-- .../org/enso/interpreter/runtime/data/vector/Array.java | 5 +++-- .../runtime/data/vector/ArrayLikeHelpers.java | 9 +++++++-- .../org/enso/interpreter/runtime/data/vector/Vector.java | 8 ++++++-- .../org/enso/interpreter/runtime/warning/Warning.java | 5 +++-- 13 files changed, 55 insertions(+), 26 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java index 5a4c655d290a..d0be8ed14ade 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java @@ -13,12 +13,16 @@ import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "date", name = "Date", stdlibName = "Standard.Base.Data.Time.Date.Date") +@Builtin( + pkg = "date", + name = EnsoDate.builtinName, + stdlibName = "Standard.Base.Data.Time.Date.Date") public final class EnsoDate extends BuiltinObject { + static final String builtinName = "Date"; private final LocalDate date; public EnsoDate(LocalDate date) { - super("Date"); + super(builtinName); this.date = date; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java index c898627900aa..721f3145bf37 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java @@ -18,13 +18,14 @@ @ExportLibrary(InteropLibrary.class) @Builtin( pkg = "date", - name = "DateTime", + name = EnsoDateTime.builtinName, stdlibName = "Standard.Base.Data.Time.Date_Time.Date_Time") public final class EnsoDateTime extends BuiltinObject { + static final String builtinName = "Date_Time"; private final ZonedDateTime dateTime; public EnsoDateTime(ZonedDateTime dateTime) { - super("Date_Time"); + super(builtinName); this.dateTime = dateTime; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java index 1408aea59fa7..8c708e6d1b4b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java @@ -18,12 +18,16 @@ import org.enso.interpreter.runtime.error.PanicException; @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "date", name = "Duration", stdlibName = "Standard.Base.Data.Time.Duration.Duration") +@Builtin( + pkg = "date", + name = EnsoDuration.builtinName, + stdlibName = "Standard.Base.Data.Time.Duration.Duration") public final class EnsoDuration extends BuiltinObject { private final Duration duration; + static final String builtinName = "Duration"; public EnsoDuration(Duration duration) { - super("Duration"); + super(builtinName); this.duration = duration; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java index dd06275e5dd8..a5d58b870fd2 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java @@ -50,12 +50,13 @@ * please refer to {@link TruffleFile}. */ @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "io", name = "File", stdlibName = "Standard.Base.System.File.File") +@Builtin(pkg = "io", name = EnsoFile.builtinName, stdlibName = "Standard.Base.System.File.File") public final class EnsoFile extends BuiltinObject { + static final String builtinName = "File"; private final TruffleFile truffleFile; public EnsoFile(TruffleFile truffleFile) { - super("File"); + super(builtinName); if (truffleFile == null) { throw CompilerDirectives.shouldNotReachHere(); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java index 62b24c0ef404..be8589a29d2b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java @@ -17,13 +17,14 @@ @ExportLibrary(InteropLibrary.class) @Builtin( pkg = "date", - name = "TimeOfDay", + name = EnsoTimeOfDay.builtinName, stdlibName = "Standard.Base.Data.Time.Time_Of_Day.Time_Of_Day") public final class EnsoTimeOfDay extends BuiltinObject { + static final String builtinName = "Time_Of_Day"; private final LocalTime localTime; public EnsoTimeOfDay(LocalTime localTime) { - super("Time_Of_Day"); + super(builtinName); this.localTime = localTime; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java index 5f5b5f2d4e8c..54a4f259449d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java @@ -18,13 +18,14 @@ @ExportLibrary(InteropLibrary.class) @Builtin( pkg = "date", - name = "TimeZone", + name = EnsoTimeZone.builtinName, stdlibName = "Standard.Base.Data.Time.Time_Zone.Time_Zone") public final class EnsoTimeZone extends BuiltinObject { + static final String builtinName = "Time_Zone"; private final ZoneId zone; public EnsoTimeZone(ZoneId zone) { - super("Time_Zone"); + super(builtinName); this.zone = zone; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java index ee817514c89c..04b71e9b052a 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java @@ -35,8 +35,12 @@ * ProcessItems} processor. */ @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "resource", stdlibName = "Standard.Base.Runtime.Managed_Resource.Managed_Resource") +@Builtin( + pkg = "resource", + stdlibName = "Standard.Base.Runtime.Managed_Resource.Managed_Resource", + name = ManagedResource.builtinName) public final class ManagedResource extends BuiltinObject { + static final String builtinName = "Managed_Resource"; private final Object resource; private final PhantomReference phantomReference; @@ -49,7 +53,7 @@ public final class ManagedResource extends BuiltinObject { public ManagedResource( Object resource, java.util.function.Function> factory) { - super("Managed_Resource"); + super(builtinName); this.resource = resource; this.phantomReference = factory.apply(this); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java index eb74b1ba4980..88f5ee9aefd7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java @@ -10,8 +10,9 @@ /** A mutable reference type. */ @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "mutable", stdlibName = "Standard.Base.Runtime.Ref.Ref") +@Builtin(pkg = "mutable", stdlibName = "Standard.Base.Runtime.Ref.Ref", name = Ref.builtinName) public final class Ref extends BuiltinObject { + static final String builtinName = "Ref"; private volatile Object value; /** @@ -21,7 +22,7 @@ public final class Ref extends BuiltinObject { */ @Builtin.Method(description = "Creates a new Ref", autoRegister = false) public Ref(Object value) { - super("Ref"); + super(builtinName); this.value = value; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java index e71ce7fa1092..b1b15840311d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java @@ -30,8 +30,9 @@ * as it works in Enso. */ @ExportLibrary(InteropLibrary.class) -@Builtin(stdlibName = "Standard.Base.Data.Dictionary.Dictionary", name = "Dictionary") +@Builtin(stdlibName = "Standard.Base.Data.Dictionary.Dictionary", name = EnsoHashMap.builtinName) public final class EnsoHashMap extends BuiltinObject { + static final String builtinName = "Dictionary"; private final EnsoHashMapBuilder mapBuilder; private final int generation; private final int size; @@ -39,7 +40,7 @@ public final class EnsoHashMap extends BuiltinObject { private Object cachedVectorRepresentation; private EnsoHashMap(EnsoHashMapBuilder mapBuilder) { - super("Dictionary"); + super(builtinName); this.mapBuilder = mapBuilder; this.generation = mapBuilder.generation(); this.size = mapBuilder.size(); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java index c96cf4dc90f0..05d439e3bc51 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java @@ -27,8 +27,9 @@ /** A primitive boxed array type for use in the runtime. */ @ExportLibrary(InteropLibrary.class) @ExportLibrary(WarningsLibrary.class) -@Builtin(pkg = "mutable", stdlibName = "Standard.Base.Data.Array.Array") +@Builtin(pkg = "mutable", stdlibName = "Standard.Base.Data.Array.Array", name = Array.builtinName) final class Array extends BuiltinObject { + static final String builtinName = "Array"; private final Object[] items; /** If true, some elements contain warning, and thus, this Array contains warning. */ @@ -44,7 +45,7 @@ final class Array extends BuiltinObject { * @param items the element values */ private Array(Object... items) { - super("Array"); + super(builtinName); this.items = items; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java index ea2cee7a0e33..b8e883026e30 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java @@ -9,10 +9,15 @@ import org.enso.interpreter.runtime.data.EnsoObject; /** Publicly available operations on array-like classes. */ -@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Internal.Array_Like_Helpers") +@Builtin( + pkg = "immutable", + stdlibName = "Standard.Base.Internal.Array_Like_Helpers", + name = ArrayLikeHelpers.builtinName) public final class ArrayLikeHelpers extends BuiltinObject { + static final String builtinName = "Array_Like_Helpers"; + private ArrayLikeHelpers() { - super("Array_Like_Helpers"); + super(builtinName); } @Builtin.Method( diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java index a82d8166cf80..a22ce98970e5 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java @@ -17,14 +17,18 @@ import org.enso.interpreter.runtime.warning.WarningsLibrary; @ExportLibrary(InteropLibrary.class) -@Builtin(pkg = "immutable", stdlibName = "Standard.Base.Data.Vector.Vector") +@Builtin( + pkg = "immutable", + stdlibName = "Standard.Base.Data.Vector.Vector", + name = Vector.builtinName) abstract class Vector extends BuiltinObject { + static final String builtinName = "Vector"; private static final Vector EMPTY_LONG = new Long(new long[0]); private static final Vector EMPTY_DOUBLE = new Double(new double[0]); private static final Vector EMPTY_VECTOR = new EnsoOnly(new Object[0]); protected Vector() { - super("Vector"); + super(builtinName); } @ExportMessage diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java index c31934f4012b..a53470919428 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java @@ -14,15 +14,16 @@ import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.hash.HashMapInsertNode; -@Builtin(pkg = "error", stdlibName = "Standard.Base.Warning.Warning") +@Builtin(pkg = "error", stdlibName = "Standard.Base.Warning.Warning", name = Warning.builtinName) @ExportLibrary(value = InteropLibrary.class, delegateTo = "value") public final class Warning extends BuiltinObject { + static final String builtinName = "Warning"; final Object value; private final Object origin; private final long sequenceId; private Warning(Object value, Object origin, long sequenceId) { - super("Warning"); + super(builtinName); this.value = value; this.origin = origin; this.sequenceId = sequenceId; From f187211da9f44db706220e61d2442013f581e0c7 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 12:21:39 +0100 Subject: [PATCH 27/44] Move BuiltinObject to package org.enso.interpreter.runtime.builtin --- .../{node/expression => runtime}/builtin/BuiltinObject.java | 3 ++- .../main/java/org/enso/interpreter/runtime/data/EnsoDate.java | 2 +- .../java/org/enso/interpreter/runtime/data/EnsoDateTime.java | 2 +- .../java/org/enso/interpreter/runtime/data/EnsoDuration.java | 2 +- .../main/java/org/enso/interpreter/runtime/data/EnsoFile.java | 2 +- .../java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java | 2 +- .../java/org/enso/interpreter/runtime/data/EnsoTimeZone.java | 2 +- .../org/enso/interpreter/runtime/data/ManagedResource.java | 2 +- .../src/main/java/org/enso/interpreter/runtime/data/Ref.java | 2 +- .../org/enso/interpreter/runtime/data/hash/EnsoHashMap.java | 2 +- .../main/java/org/enso/interpreter/runtime/data/text/Text.java | 2 +- .../java/org/enso/interpreter/runtime/data/vector/Array.java | 2 +- .../enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java | 2 +- .../org/enso/interpreter/runtime/data/vector/ArrayProxy.java | 2 +- .../java/org/enso/interpreter/runtime/data/vector/Vector.java | 2 +- .../org/enso/interpreter/runtime/number/EnsoBigInteger.java | 2 +- .../java/org/enso/interpreter/runtime/warning/Warning.java | 2 +- 17 files changed, 18 insertions(+), 17 deletions(-) rename engine/runtime/src/main/java/org/enso/interpreter/{node/expression => runtime}/builtin/BuiltinObject.java (97%) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java similarity index 97% rename from engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java rename to engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java index 402300a25e36..c4aa775189a3 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -1,4 +1,4 @@ -package org.enso.interpreter.node.expression.builtin; +package org.enso.interpreter.runtime.builtin; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -15,6 +15,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.enso.interpreter.node.expression.builtin.Builtin; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.function.Function; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java index d0be8ed14ade..8579d8b317f4 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDate.java @@ -9,7 +9,7 @@ import java.time.LocalDate; import java.time.LocalTime; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.polyglot.common_utils.Core_Date_Utils; @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java index 721f3145bf37..18b206eeeb83 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDateTime.java @@ -11,7 +11,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; import org.enso.polyglot.common_utils.Core_Date_Utils; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java index 8c708e6d1b4b..787ea8d66ce6 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoDuration.java @@ -13,8 +13,8 @@ import java.time.ZonedDateTime; import java.time.temporal.Temporal; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.error.PanicException; @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java index a5d58b870fd2..a5d5c01925d3 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoFile.java @@ -36,8 +36,8 @@ import java.util.Set; import java.util.function.Function; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.data.vector.ArrayLikeAtNode; import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java index be8589a29d2b..86db62dbcf93 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeOfDay.java @@ -11,7 +11,7 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java index 54a4f259449d..c16a71d6998e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoTimeZone.java @@ -11,7 +11,7 @@ import java.time.ZoneOffset; import java.time.zone.ZoneRulesException; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.text.Text; import org.enso.polyglot.common_utils.Core_Date_Utils; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java index 04b71e9b052a..3d3078a20a99 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/ManagedResource.java @@ -9,8 +9,8 @@ import com.oracle.truffle.api.nodes.Node; import java.lang.ref.PhantomReference; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.callable.function.Function; /** diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java index 88f5ee9aefd7..453c8c7ef20f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Ref.java @@ -6,7 +6,7 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; /** A mutable reference type. */ @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java index b1b15840311d..f8c029d9e32d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/hash/EnsoHashMap.java @@ -12,10 +12,10 @@ import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.profiles.ConditionProfile; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.builtin.meta.EqualsNode; import org.enso.interpreter.node.expression.builtin.meta.HashCodeNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.hash.EnsoHashMapBuilder.StorageEntry; import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java index 17bc028a1aed..8408b1db703d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java @@ -13,8 +13,8 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.polyglot.common_utils.Core_Text_Utils; /** The main runtime type for Enso's Text. */ diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java index 05d439e3bc51..c3d63f8dd8de 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Array.java @@ -14,8 +14,8 @@ import java.util.Arrays; import java.util.Comparator; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.hash.HashMapInsertAllNode; import org.enso.interpreter.runtime.data.hash.HashMapInsertNode; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java index b8e883026e30..b5e17e2d511c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayLikeHelpers.java @@ -5,7 +5,7 @@ import com.oracle.truffle.api.library.CachedLibrary; import java.nio.ByteBuffer; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.EnsoObject; /** Publicly available operations on array-like classes. */ diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java index 6c89f4e8df88..5ec5305d1ee9 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java @@ -13,7 +13,7 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; /** * A wrapper that allows to turn an Enso callback providing elements into a polyglot Array. diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java index a22ce98970e5..ab55ed86978e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/Vector.java @@ -9,9 +9,9 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.node.expression.foreign.HostValueToEnsoNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.warning.AppendWarningNode; import org.enso.interpreter.runtime.warning.WarningsLibrary; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java index 8f10990bf0ec..440ab7139a77 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java @@ -6,7 +6,7 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import java.math.BigInteger; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; +import org.enso.interpreter.runtime.builtin.BuiltinObject; /** Internal wrapper for a {@link BigInteger}. */ @ExportLibrary(InteropLibrary.class) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java index a53470919428..5d064e0e8f3c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/warning/Warning.java @@ -9,8 +9,8 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import org.enso.interpreter.dsl.Builtin; -import org.enso.interpreter.node.expression.builtin.BuiltinObject; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; import org.enso.interpreter.runtime.data.hash.EnsoHashMap; import org.enso.interpreter.runtime.data.hash.HashMapInsertNode; From 0cc0b72be8b8a5db0ae25bdec5b14b1f197afdde Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 12:31:00 +0100 Subject: [PATCH 28/44] Fix FQN of BuiltinObject in the annotation processor --- .../main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java index 8ea63ea0d112..6d9a4322ece3 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java @@ -352,7 +352,7 @@ private int specializationsCount(Element owner, String builtinMethodName) { * @param builtinClass Class annotated with {@link Builtin}. */ private void ensureBuiltinClassExtendsBuiltinObject(TypeElement builtinClass) { - var builtinObjectBinName = "org.enso.interpreter.node.expression.builtin.BuiltinObject"; + var builtinObjectBinName = "org.enso.interpreter.runtime.builtin.BuiltinObject"; if (!isSubtype(builtinClass, builtinObjectBinName)) { processingEnv .getMessager() From 6f31ebfff7e2ec6f88d9b3a374150484c8253567 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 12:38:42 +0100 Subject: [PATCH 29/44] Make exported messages on BuiltinObject final --- .../runtime/builtin/BuiltinObject.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java index c4aa775189a3..e0f934cccd43 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -51,32 +51,32 @@ protected BuiltinObject(String builtinName) { } @ExportMessage - public boolean hasMembers() { + public final boolean hasMembers() { return true; } @ExportMessage @TruffleBoundary - public Object getMembers(boolean includeInternal, @Bind("$node") Node node) { + public final Object getMembers(boolean includeInternal, @Bind("$node") Node node) { var methodNamesArr = methodNames().toArray(String[]::new); return ArrayLikeHelpers.wrapStrings(methodNamesArr); } @ExportMessage @TruffleBoundary - public boolean isMemberReadable(String member) { + public final boolean isMemberReadable(String member) { return methodNames().contains(member); } @ExportMessage @TruffleBoundary - public boolean isMemberInvocable(String member) { + public final boolean isMemberInvocable(String member) { return isMemberReadable(member); } @ExportMessage @TruffleBoundary - public Object readMember(String member) throws UnknownIdentifierException { + public final Object readMember(String member) throws UnknownIdentifierException { if (!isMemberReadable(member)) { throw UnknownIdentifierException.create(member); } @@ -89,24 +89,24 @@ public Object readMember(String member) throws UnknownIdentifierException { @ExportMessage @TruffleBoundary - public Object invokeMember(String member, Object[] args) + public final Object invokeMember(String member, Object[] args) throws UnsupportedMessageException, UnsupportedTypeException, ArityException { var ctx = EnsoContext.get(null); var sym = UnresolvedSymbol.build(member, ctx.getBuiltins().getScope()); var argsForBuiltin = new Object[args.length + 1]; argsForBuiltin[0] = this; - System.arraycopy(args, 0, argsForBuiltin, 1, args.length); + java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); var interop = InteropLibrary.getUncached(); return interop.execute(sym, argsForBuiltin); } @ExportMessage - public boolean hasType() { + public final boolean hasType() { return true; } @ExportMessage - public Type getType(@Bind("$node") Node node) { + public final Type getType(@Bind("$node") Node node) { if (cachedBuiltinType == null) { CompilerDirectives.transferToInterpreter(); var ctx = EnsoContext.get(node); @@ -116,12 +116,12 @@ public Type getType(@Bind("$node") Node node) { } @ExportMessage - public boolean hasMetaObject() { + public final boolean hasMetaObject() { return true; } @ExportMessage - public Type getMetaObject(@Bind("$node") Node node) { + public final Type getMetaObject(@Bind("$node") Node node) { return getType(node); } From 2462523a5c3e4f9cf52a2fa8248b67f704e8bf7a Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 12:39:52 +0100 Subject: [PATCH 30/44] Update generated class names in Builtins. Fixes compilation after 8acb04a4f948ab28ea028c55e6035ea35256799e --- .../org/enso/interpreter/runtime/builtin/Builtins.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java index 306c3758d07f..e8678a041a70 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java @@ -45,7 +45,7 @@ import org.enso.interpreter.node.expression.builtin.ordering.Comparable; import org.enso.interpreter.node.expression.builtin.ordering.DefaultComparator; import org.enso.interpreter.node.expression.builtin.ordering.Ordering; -import org.enso.interpreter.node.expression.builtin.resource.ManagedResource; +import org.enso.interpreter.node.expression.builtin.resource.Managed_Resource; import org.enso.interpreter.node.expression.builtin.runtime.Context; import org.enso.interpreter.node.expression.builtin.text.Text; import org.enso.interpreter.runtime.EnsoContext; @@ -163,15 +163,15 @@ public Builtins(EnsoContext context) { dictionary = builtins.get(org.enso.interpreter.node.expression.builtin.Dictionary.class); dataflowError = builtins.get(org.enso.interpreter.node.expression.builtin.Error.class); ref = builtins.get(Ref.class); - managedResource = builtins.get(ManagedResource.class); + managedResource = builtins.get(Managed_Resource.class); debug = builtins.get(Debug.class); projectDescription = getBuiltinType(ProjectDescription.class); file = builtins.get(File.class); date = builtins.get(org.enso.interpreter.node.expression.builtin.date.Date.class); - dateTime = builtins.get(org.enso.interpreter.node.expression.builtin.date.DateTime.class); + dateTime = builtins.get(org.enso.interpreter.node.expression.builtin.date.Date_Time.class); duration = builtins.get(org.enso.interpreter.node.expression.builtin.date.Duration.class); - timeOfDay = builtins.get(org.enso.interpreter.node.expression.builtin.date.TimeOfDay.class); - timeZone = builtins.get(org.enso.interpreter.node.expression.builtin.date.TimeZone.class); + timeOfDay = builtins.get(org.enso.interpreter.node.expression.builtin.date.Time_Of_Day.class); + timeZone = builtins.get(org.enso.interpreter.node.expression.builtin.date.Time_Zone.class); warning = builtins.get(Warning.class); noWrap = getBuiltinType(NoWrap.class); problemBehavior = getBuiltinType(ProblemBehavior.class); From e441faba5b21b4d38498edc3a0bb614a35c5b64b Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 10 Dec 2024 14:39:01 +0100 Subject: [PATCH 31/44] Exported messages in BuiltinObject are not behind TruffleBoundary --- .../runtime/builtin/BuiltinObject.java | 156 ++++++++++++------ 1 file changed, 109 insertions(+), 47 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java index e0f934cccd43..635a946b87a2 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -1,19 +1,25 @@ package org.enso.interpreter.runtime.builtin; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Cached.Shared; +import com.oracle.truffle.api.dsl.NeverDefault; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.LoopConditionProfile; import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import org.enso.interpreter.node.expression.builtin.Builtin; import org.enso.interpreter.runtime.EnsoContext; @@ -39,9 +45,16 @@ public abstract class BuiltinObject extends EnsoObject { private final String builtinName; - private Map methods; + + @CompilationFinal private Builtin cachedBuiltinType; + @CompilationFinal(dimensions = 1) + private String[] methodNames; + + @CompilationFinal(dimensions = 1) + private Function[] methods; + /** * @param builtinName Simple name of the builtin that should be contained in {@link * org.enso.interpreter.runtime.builtin.Builtins#builtinsByName}. @@ -56,48 +69,85 @@ public final boolean hasMembers() { } @ExportMessage - @TruffleBoundary - public final Object getMembers(boolean includeInternal, @Bind("$node") Node node) { - var methodNamesArr = methodNames().toArray(String[]::new); - return ArrayLikeHelpers.wrapStrings(methodNamesArr); + public final Object getMembers(boolean includeInternal) { + return ArrayLikeHelpers.wrapStrings(methodNames()); } @ExportMessage - @TruffleBoundary - public final boolean isMemberReadable(String member) { - return methodNames().contains(member); + public final boolean isMemberReadable( + String member, @Shared @Cached LoopConditionProfile loopProfile) { + var size = methodNames().length; + loopProfile.profileCounted(size); + for (var i = 0; loopProfile.inject(i < methodNames.length); i++) { + var methodName = methodNames[i]; + if (member.compareTo(methodName) == 0) { + return true; + } + } + return false; } @ExportMessage - @TruffleBoundary - public final boolean isMemberInvocable(String member) { - return isMemberReadable(member); + public final boolean isMemberInvocable( + String member, @Shared @Cached LoopConditionProfile loopProfile) { + return isMemberReadable(member, loopProfile); } @ExportMessage - @TruffleBoundary - public final Object readMember(String member) throws UnknownIdentifierException { - if (!isMemberReadable(member)) { - throw UnknownIdentifierException.create(member); - } - var func = methods().get(member); - if (func != null) { - return func; + public final Object readMember(String member, @Shared @Cached LoopConditionProfile loopProfile) + throws UnknownIdentifierException { + var methodNames = methodNames(); + var methods = methods(); + loopProfile.profileCounted(methodNames.length); + for (var i = 0; loopProfile.inject(i < methodNames.length); i++) { + var methodName = methodNames[i]; + if (methodName.compareTo(member) == 0) { + return methods[i]; + } } throw UnknownIdentifierException.create(member); } @ExportMessage - @TruffleBoundary - public final Object invokeMember(String member, Object[] args) - throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - var ctx = EnsoContext.get(null); - var sym = UnresolvedSymbol.build(member, ctx.getBuiltins().getScope()); - var argsForBuiltin = new Object[args.length + 1]; - argsForBuiltin[0] = this; - java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); - var interop = InteropLibrary.getUncached(); - return interop.execute(sym, argsForBuiltin); + public static final class InvokeMember { + @Specialization( + guards = {"cachedMember.equals(member)"}, + limit = "3") + public static Object doCached( + BuiltinObject receiver, + String member, + Object[] args, + @Cached("member") String cachedMember, + @Cached("buildSymbol(cachedMember)") UnresolvedSymbol cachedSymbol, + @CachedLibrary("cachedSymbol") InteropLibrary interop) + throws UnsupportedMessageException, UnsupportedTypeException, ArityException { + var argsForBuiltin = new Object[args.length + 1]; + argsForBuiltin[0] = receiver; + java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); + return interop.execute(cachedSymbol, argsForBuiltin); + } + + @Specialization(replaces = "doCached") + public static Object doUncached( + BuiltinObject receiver, + String member, + Object[] args, + @CachedLibrary(limit = "3") InteropLibrary interop) + throws UnsupportedMessageException, UnsupportedTypeException, ArityException { + var ctx = EnsoContext.get(interop); + var symbol = buildSymbol(member, ctx); + return doCached(receiver, member, args, member, symbol, interop); + } + + private static UnresolvedSymbol buildSymbol(String symbol, EnsoContext ctx) { + return UnresolvedSymbol.build(symbol, ctx.getBuiltins().getScope()); + } + + @NeverDefault + public static UnresolvedSymbol buildSymbol(String symbol) { + var ctx = EnsoContext.get(null); + return buildSymbol(symbol, ctx); + } } @ExportMessage @@ -125,31 +175,43 @@ public final Type getMetaObject(@Bind("$node") Node node) { return getType(node); } - private Map methods() { + @TruffleBoundary + private Map findMethods() { var ctx = EnsoContext.get(null); - if (methods == null) { - var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); - assert builtinType != null; - var defScope = builtinType.getType().getDefinitionScope(); - var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); - assert methodsFromScope != null; - methods = new HashMap<>(); - for (var method : methodsFromScope) { - var methodName = normalizeName(method.getName()); - methods.put(methodName, method); - } + var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); + assert builtinType != null; + var defScope = builtinType.getType().getDefinitionScope(); + var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); + assert methodsFromScope != null; + var methods = new HashMap(); + for (var method : methodsFromScope) { + var methodName = normalizeName(method.getName()); + methods.put(methodName, method); } return methods; } - private Set methodNames() { - var methodNames = - methods().keySet().stream() - .map(BuiltinObject::normalizeName) - .collect(Collectors.toUnmodifiableSet()); + private String[] methodNames() { + if (methodNames == null) { + CompilerDirectives.transferToInterpreter(); + var methods = findMethods(); + var namesSet = + methods.keySet().stream() + .map(BuiltinObject::normalizeName) + .collect(Collectors.toUnmodifiableSet()); + methodNames = namesSet.toArray(String[]::new); + } return methodNames; } + private Function[] methods() { + if (methods == null) { + CompilerDirectives.transferToInterpreter(); + methods = findMethods().values().toArray(Function[]::new); + } + return methods; + } + private static String normalizeName(String funcName) { var funcNameItems = funcName.split("\\."); return funcNameItems[funcNameItems.length - 1]; From a77691c5a5fc9a7b9c934931d4d6c9ee27ff8412 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 11 Dec 2024 14:00:00 +0100 Subject: [PATCH 32/44] [WIP] Add BuiltinsJavaInteropTest --- .../org/enso/example/PolyglotTestClass.java | 18 +++++ .../builtins/BuiltinsJavaInteropTest.java | 78 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 engine/runtime-integration-tests/src/test/java/org/enso/example/PolyglotTestClass.java create mode 100644 engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/example/PolyglotTestClass.java b/engine/runtime-integration-tests/src/test/java/org/enso/example/PolyglotTestClass.java new file mode 100644 index 000000000000..928163f894db --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/example/PolyglotTestClass.java @@ -0,0 +1,18 @@ +package org.enso.example; + +import java.time.LocalDate; +import org.graalvm.polyglot.Value; + +public class PolyglotTestClass { + public static boolean isPolyglotDate_Object(Object obj) { + return obj instanceof Value polyglotVal && polyglotVal.isDate(); + } + + public static boolean isPolyglotDate_LocalDate(LocalDate date) { + return date != null; + } + + public static boolean isPolyglotDate_Value(Value val) { + return val != null && val.isDate(); + } +} diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java new file mode 100644 index 000000000000..7f0d57b5d097 --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java @@ -0,0 +1,78 @@ +package org.enso.interpreter.test.builtins; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.containsString; + +import java.io.ByteArrayOutputStream; +import org.enso.test.utils.ContextUtils; +import org.graalvm.polyglot.Context; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BuiltinsJavaInteropTest { + private static Context ctx; + private static final ByteArrayOutputStream out = new ByteArrayOutputStream(); + + @BeforeClass + public static void prepareCtx() { + ctx = ContextUtils.createDefaultContext(out); + } + + @AfterClass + public static void disposeCtx() { + ctx.close(); + ctx = null; + } + + @After + public void resetOutput() { + out.reset(); + } + + @Test + public void javaMethodAcceptsEnsoTimeOfDay_AsObject() { + var src = """ + from Standard.Base import Date_Time + polyglot java import org.enso.example.PolyglotTestClass + + main = + dt = Date_Time.now + PolyglotTestClass.isPolyglotDate_Object dt + """; + var result = ContextUtils.evalModule(ctx, src); + assertThat(result.asBoolean(), is(true)); + } + + @Test + public void javaMethodAcceptsEnsoTimeOfDay_AsLocalDate() { + var src = """ + from Standard.Base import Date_Time + polyglot java import org.enso.example.PolyglotTestClass + + main = + dt = Date_Time.now + PolyglotTestClass.isPolyglotDate_LocalDate dt + """; + var result = ContextUtils.evalModule(ctx, src); + assertThat(result.asBoolean(), is(true)); + } + + @Test + public void javaMethodAcceptsEnsoTimeOfDay_AsValue() { + var src = """ + from Standard.Base import Date_Time + polyglot java import org.enso.example.PolyglotTestClass + + main = + dt = Date_Time.now + PolyglotTestClass.isPolyglotDate_Value dt + """; + var result = ContextUtils.evalModule(ctx, src); + assertThat(result.asBoolean(), is(true)); + } + +} From b6ec2ae5ed3a3c234fe4fcc1a11ee4d4eb3c6f76 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Wed, 11 Dec 2024 19:01:48 +0100 Subject: [PATCH 33/44] Storage.vectorizedOrFallbackBinaryMap accepts Value as parameter --- .../org/enso/table/data/column/storage/Storage.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/std-bits/table/src/main/java/org/enso/table/data/column/storage/Storage.java b/std-bits/table/src/main/java/org/enso/table/data/column/storage/Storage.java index c9c8c258fdad..ad386ebbb6ff 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/column/storage/Storage.java +++ b/std-bits/table/src/main/java/org/enso/table/data/column/storage/Storage.java @@ -224,14 +224,20 @@ public final Storage vectorizedOrFallbackBinaryMap( String name, MapOperationProblemAggregator problemAggregator, BiFunction fallback, - Object argument, + Value argument, boolean skipNulls, StorageType expectedResultType) { + Object convertedArg; + if (argument.isHostObject()) { + convertedArg = argument.asHostObject(); + } else { + convertedArg = Polyglot_Utils.convertPolyglotValue(argument); + } if (isBinaryOpVectorized(name)) { - return runVectorizedBinaryMap(name, argument, problemAggregator); + return runVectorizedBinaryMap(name, convertedArg, problemAggregator); } else { checkFallback(fallback, expectedResultType, name); - return binaryMap(fallback, argument, skipNulls, expectedResultType, problemAggregator); + return binaryMap(fallback, convertedArg, skipNulls, expectedResultType, problemAggregator); } } From 752ac901a54757b329cbdc229ee2795bdc9a12e7 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 17:28:17 +0100 Subject: [PATCH 34/44] Builtin types expose methods, not BuiltinObject --- ...ava => BuiltinTypesExposeMethodsTest.java} | 66 +++------ .../enso/interpreter/runtime/data/Type.java | 126 +++++++++++++++++- 2 files changed, 139 insertions(+), 53 deletions(-) rename engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/{BuiltinsExposeMethodsTest.java => BuiltinTypesExposeMethodsTest.java} (56%) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinTypesExposeMethodsTest.java similarity index 56% rename from engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java rename to engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinTypesExposeMethodsTest.java index db547df94d7e..7d750c4b72d0 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsExposeMethodsTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinTypesExposeMethodsTest.java @@ -4,7 +4,6 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import com.oracle.truffle.api.interop.InteropLibrary; import java.util.ArrayList; import java.util.List; import org.enso.interpreter.runtime.data.Type; @@ -26,13 +25,13 @@ * checks that {@link Value#canInvokeMember(String)} returns true. */ @RunWith(Parameterized.class) -public class BuiltinsExposeMethodsTest { +public class BuiltinTypesExposeMethodsTest { private static Context ctx; - private final ValueWithType valueWithType; + private final Value type; - public BuiltinsExposeMethodsTest(ValueWithType valueWithType) { - this.valueWithType = valueWithType; + public BuiltinTypesExposeMethodsTest(Value type) { + this.type = type; } private static Context ctx() { @@ -43,21 +42,22 @@ private static Context ctx() { } @Parameters(name = "{index}: {0}") - public static Iterable generateBuiltinObjects() { + public static Iterable generateBuiltinObjects() { var valuesGenerator = ValuesGenerator.create(ctx(), Language.ENSO); - var builtinObjectsWithTypes = new ArrayList(); + var builtinTypes = new ArrayList(); ContextUtils.executeInContext( ctx(), () -> { - valuesGenerator.allValues().stream() - .map(val -> new ValueWithType(val, getType(val))) - .filter(valWithType -> !shouldSkipType(valWithType.type)) - .filter(valWithType -> !isPrimitive(valWithType.value)) - .filter(valWithType -> !isHostValue(valWithType.value)) - .forEach(builtinObjectsWithTypes::add); + valuesGenerator.allTypes().stream() + .filter( + val -> { + var asType = getType(val); + return !shouldSkipType(asType); + }) + .forEach(builtinTypes::add); return null; }); - return builtinObjectsWithTypes; + return builtinTypes; } private static Type getType(Value object) { @@ -78,10 +78,9 @@ public void builtinExposeMethods() { ContextUtils.executeInContext( ctx(), () -> { - assertThat(valueWithType, is(notNullValue())); - assertThat(valueWithType.type.isBuiltin(), is(true)); - var typeDefScope = valueWithType.type.getDefinitionScope(); - var methodsDefinedInScope = typeDefScope.getMethodsForType(valueWithType.type); + assertThat(type, is(notNullValue())); + var typeDefScope = getType(type).getDefinitionScope(); + var methodsDefinedInScope = typeDefScope.getMethodsForType(getType(type)); if (methodsDefinedInScope != null) { for (var methodInScope : methodsDefinedInScope) { var methodName = methodInScope.getName(); @@ -90,23 +89,14 @@ public void builtinExposeMethods() { methodName = items[items.length - 1]; } assertThat( - "Builtin type " + valueWithType.type.getQualifiedName() + " should have members", - valueWithType.value.hasMembers(), - is(true)); + "Builtin type " + type + " should have members", type.hasMembers(), is(true)); assertThat( "Member " + methodName + " should be present", - valueWithType.value.hasMember(methodName), + type.hasMember(methodName), is(true)); assertThat( "Member " + methodName + " should be invocable", - valueWithType.value.canInvokeMember(methodName), - is(true)); - var interop = InteropLibrary.getUncached(); - var unwrappedValue = ContextUtils.unwrapValue(ctx(), valueWithType.value); - var memberViaInterop = interop.readMember(unwrappedValue, methodName); - assertThat( - "Member via interop should be the same as in scope, but was: " + memberViaInterop, - memberViaInterop == methodInScope, + type.canInvokeMember(methodName), is(true)); } } @@ -114,14 +104,6 @@ public void builtinExposeMethods() { }); } - private static boolean isPrimitive(Value object) { - var unwrapped = ContextUtils.unwrapValue(ctx(), object); - return unwrapped instanceof Long - || unwrapped instanceof Boolean - || unwrapped instanceof Integer - || unwrapped instanceof Double; - } - private static boolean shouldSkipType(Type type) { if (type == null) { return true; @@ -136,12 +118,4 @@ private static boolean shouldSkipType(Type type) { var shouldBeSkipped = typesToSkip.stream().anyMatch(toSkip -> toSkip == type); return shouldBeSkipped; } - - private static boolean isHostValue(Value value) { - var unwrapped = ContextUtils.unwrapValue(ctx(), value); - var ensoCtx = ContextUtils.leakContext(ctx()); - return ensoCtx.isJavaPolyglotObject(unwrapped); - } - - public record ValueWithType(Value value, Type type) {} } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java index 754218d22988..039ea8c8cc2d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java @@ -3,9 +3,14 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.NeverDefault; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -13,12 +18,14 @@ import com.oracle.truffle.api.nodes.Node; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Objects; import org.enso.interpreter.Constants; import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.node.ConstantNode; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; @@ -41,6 +48,7 @@ public final class Type extends EnsoObject { private final boolean isProjectPrivate; private boolean gettersGenerated; + private Map methods; private Type( String name, @@ -337,13 +345,25 @@ boolean hasMembers() { return true; } + /** + * Members are constructors and methods from this type, and eigen type. Not extension methods as + * they are most likely not in the module scope of this type. + * + * @param includeInternal + * @return + */ @ExportMessage @CompilerDirectives.TruffleBoundary EnsoObject getMembers(boolean includeInternal) { if (isProjectPrivate) { return ArrayLikeHelpers.empty(); } else { - return ArrayLikeHelpers.wrapStrings(constructors.keySet().toArray(String[]::new)); + var consNames = constructors.keySet(); + var methodNames = methods().keySet(); + var allNames = new HashSet(); + allNames.addAll(consNames); + allNames.addAll(methodNames); + return ArrayLikeHelpers.wrapStrings(allNames.toArray(String[]::new)); } } @@ -353,7 +373,54 @@ boolean isMemberReadable(String member) { if (isProjectPrivate) { return false; } else { - return constructors.containsKey(member); + return constructors.containsKey(member) || methods().containsKey(member); + } + } + + @ExportMessage + boolean isMemberInvocable(String member) { + return methods().containsKey(member); + } + + @ExportMessage + static final class InvokeMember { + @Specialization( + guards = {"cachedMember.equals(member)"}, + limit = "3") + static Object doCached( + Type receiver, + String member, + Object[] args, + @Cached("member") String cachedMember, + @Cached("buildSymbol(cachedMember)") UnresolvedSymbol cachedSymbol, + @CachedLibrary("cachedSymbol") InteropLibrary interop) + throws UnsupportedMessageException, UnsupportedTypeException, ArityException { + var argsForBuiltin = new Object[args.length + 1]; + argsForBuiltin[0] = receiver; + java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); + return interop.execute(cachedSymbol, argsForBuiltin); + } + + @Specialization(replaces = "doCached") + static Object doUncached( + Type receiver, + String member, + Object[] args, + @CachedLibrary(limit = "3") InteropLibrary interop) + throws UnsupportedMessageException, UnsupportedTypeException, ArityException { + var ctx = EnsoContext.get(interop); + var symbol = buildSymbol(member, ctx); + return doCached(receiver, member, args, member, symbol, interop); + } + + private static UnresolvedSymbol buildSymbol(String symbol, EnsoContext ctx) { + return UnresolvedSymbol.build(symbol, ctx.getBuiltins().getScope()); + } + + @NeverDefault + static UnresolvedSymbol buildSymbol(String symbol) { + var ctx = EnsoContext.get(null); + return buildSymbol(symbol, ctx); } } @@ -363,12 +430,15 @@ Object readMember(String member) throws UnknownIdentifierException { if (isProjectPrivate) { throw UnknownIdentifierException.create(member); } - var result = constructors.get(member); - if (result == null) { - throw UnknownIdentifierException.create(member); - } else { - return result; + var cons = constructors.get(member); + if (cons != null) { + return cons; + } + var method = methods().get(member); + if (method != null) { + return method; } + throw UnknownIdentifierException.create(member); } @ExportMessage @@ -407,4 +477,46 @@ private boolean isNothing(Node lib) { var b = EnsoContext.get(lib).getBuiltins(); return this == b.nothing(); } + + private Map methods() { + if (methods == null) { + var allMethods = new HashMap(); + var defScope = definitionScope.asModuleScope(); + var methodsFromThisScope = defScope.getMethodsForType(this); + if (methodsFromThisScope != null) { + methodsFromThisScope.forEach( + func -> { + var simpleName = simpleFuncName(func); + allMethods.put(simpleName, func); + }); + } + if (eigentype != null) { + var methodsFromEigenScope = eigentype.getDefinitionScope().getMethodsForType(eigentype); + if (methodsFromEigenScope != null) { + methodsFromEigenScope.forEach( + func -> { + var simpleName = simpleFuncName(func); + allMethods.put(simpleName, func); + }); + } + } + methods = allMethods; + } + return methods; + } + + private static String simpleFuncName(Function func) { + assert func.getName() != null; + if (func.getName().contains(".")) { + var items = func.getName().split("\\."); + return items[items.length - 1]; + } + return func.getName(); + } + + /** + * @param simpleName Non-qualified name of the method. + * @param function The method. + */ + private record MethodWithName(String simpleName, Function function) {} } From 3a3f302004e694b528a3a911526b31477d3ae164 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 17:34:04 +0100 Subject: [PATCH 35/44] BuiltinObject has no members --- .../runtime/builtin/BuiltinObject.java | 172 ++---------------- 1 file changed, 19 insertions(+), 153 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java index 635a946b87a2..26051817c7e2 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -2,32 +2,16 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Cached.Shared; -import com.oracle.truffle.api.dsl.NeverDefault; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.LoopConditionProfile; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; import org.enso.interpreter.node.expression.builtin.Builtin; 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.data.EnsoObject; import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** @@ -46,14 +30,7 @@ public abstract class BuiltinObject extends EnsoObject { private final String builtinName; - @CompilationFinal - private Builtin cachedBuiltinType; - - @CompilationFinal(dimensions = 1) - private String[] methodNames; - - @CompilationFinal(dimensions = 1) - private Function[] methods; + @CompilationFinal private Builtin cachedBuiltinType; /** * @param builtinName Simple name of the builtin that should be contained in {@link @@ -63,93 +40,6 @@ protected BuiltinObject(String builtinName) { this.builtinName = builtinName; } - @ExportMessage - public final boolean hasMembers() { - return true; - } - - @ExportMessage - public final Object getMembers(boolean includeInternal) { - return ArrayLikeHelpers.wrapStrings(methodNames()); - } - - @ExportMessage - public final boolean isMemberReadable( - String member, @Shared @Cached LoopConditionProfile loopProfile) { - var size = methodNames().length; - loopProfile.profileCounted(size); - for (var i = 0; loopProfile.inject(i < methodNames.length); i++) { - var methodName = methodNames[i]; - if (member.compareTo(methodName) == 0) { - return true; - } - } - return false; - } - - @ExportMessage - public final boolean isMemberInvocable( - String member, @Shared @Cached LoopConditionProfile loopProfile) { - return isMemberReadable(member, loopProfile); - } - - @ExportMessage - public final Object readMember(String member, @Shared @Cached LoopConditionProfile loopProfile) - throws UnknownIdentifierException { - var methodNames = methodNames(); - var methods = methods(); - loopProfile.profileCounted(methodNames.length); - for (var i = 0; loopProfile.inject(i < methodNames.length); i++) { - var methodName = methodNames[i]; - if (methodName.compareTo(member) == 0) { - return methods[i]; - } - } - throw UnknownIdentifierException.create(member); - } - - @ExportMessage - public static final class InvokeMember { - @Specialization( - guards = {"cachedMember.equals(member)"}, - limit = "3") - public static Object doCached( - BuiltinObject receiver, - String member, - Object[] args, - @Cached("member") String cachedMember, - @Cached("buildSymbol(cachedMember)") UnresolvedSymbol cachedSymbol, - @CachedLibrary("cachedSymbol") InteropLibrary interop) - throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - var argsForBuiltin = new Object[args.length + 1]; - argsForBuiltin[0] = receiver; - java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); - return interop.execute(cachedSymbol, argsForBuiltin); - } - - @Specialization(replaces = "doCached") - public static Object doUncached( - BuiltinObject receiver, - String member, - Object[] args, - @CachedLibrary(limit = "3") InteropLibrary interop) - throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - var ctx = EnsoContext.get(interop); - var symbol = buildSymbol(member, ctx); - return doCached(receiver, member, args, member, symbol, interop); - } - - private static UnresolvedSymbol buildSymbol(String symbol, EnsoContext ctx) { - return UnresolvedSymbol.build(symbol, ctx.getBuiltins().getScope()); - } - - @NeverDefault - public static UnresolvedSymbol buildSymbol(String symbol) { - var ctx = EnsoContext.get(null); - return buildSymbol(symbol, ctx); - } - } - @ExportMessage public final boolean hasType() { return true; @@ -165,55 +55,31 @@ public final Type getType(@Bind("$node") Node node) { return cachedBuiltinType.getType(); } + /** + * Must return false, otherwise if a builtin object is passed to a host method that has a single + * {@code Object} argument, host interop would convert the builtin object to a {@code Map} with + * all its members. Even if the builtin object is, e.g., a number of a date. + * + *

Must return false as long as all our stdlib Java methods accept {@code Object} and not + * {@link org.graalvm.polyglot.Value} as arguments comming from Enso. + */ @ExportMessage - public final boolean hasMetaObject() { - return true; + public final boolean hasMembers() { + return false; } @ExportMessage - public final Type getMetaObject(@Bind("$node") Node node) { - return getType(node); + public final Object getMembers(boolean includeInternal) throws UnsupportedMessageException { + throw UnsupportedMessageException.create(); } - @TruffleBoundary - private Map findMethods() { - var ctx = EnsoContext.get(null); - var builtinType = ctx.getBuiltins().getBuiltinType(builtinName); - assert builtinType != null; - var defScope = builtinType.getType().getDefinitionScope(); - var methodsFromScope = defScope.getMethodsForType(builtinType.getType()); - assert methodsFromScope != null; - var methods = new HashMap(); - for (var method : methodsFromScope) { - var methodName = normalizeName(method.getName()); - methods.put(methodName, method); - } - return methods; - } - - private String[] methodNames() { - if (methodNames == null) { - CompilerDirectives.transferToInterpreter(); - var methods = findMethods(); - var namesSet = - methods.keySet().stream() - .map(BuiltinObject::normalizeName) - .collect(Collectors.toUnmodifiableSet()); - methodNames = namesSet.toArray(String[]::new); - } - return methodNames; - } - - private Function[] methods() { - if (methods == null) { - CompilerDirectives.transferToInterpreter(); - methods = findMethods().values().toArray(Function[]::new); - } - return methods; + @ExportMessage + public final boolean hasMetaObject() { + return true; } - private static String normalizeName(String funcName) { - var funcNameItems = funcName.split("\\."); - return funcNameItems[funcNameItems.length - 1]; + @ExportMessage + public final Type getMetaObject(@Bind("$node") Node node) { + return getType(node); } } From 6f40c6599923a603c2f14b8119e16b7240289484 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:20:02 +0100 Subject: [PATCH 36/44] Remove test Text.is_empty Text is a builtin type with Builtins module scope, which does not have `is_empty` method. --- .../InvokeBuiltinMethodViaInteropTest.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java index 6f01bf18e2a5..62fc413cc6d0 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java @@ -94,27 +94,4 @@ public void invokePlusOnTextWithParameter() { return null; }); } - - /** - * 'Text.is_empty' is not a builtin method, defined on a builtin type. It should be treated as a - * builtin method, thus be invocable via interop. - */ - @Test - public void invokeNonBuiltinMethodOnBuiltinType() { - var text = ContextUtils.evalModule(ctx, "main = 'Hello'"); - ContextUtils.executeInContext( - ctx, - () -> { - var interop = InteropLibrary.getUncached(); - var textUnwrapped = ContextUtils.unwrapValue(ctx, text); - assertThat( - "Text should have a 'is_empty' method", - interop.isMemberInvocable(textUnwrapped, "is_empty"), - is(true)); - var res = interop.invokeMember(textUnwrapped, "is_empty"); - assertThat("Text.is_empty should return a boolean", interop.isBoolean(res), is(true)); - assertThat("Text.is_empty should return false", interop.asBoolean(res), is(false)); - return null; - }); - } } From c34408b852f91b3983d86dbf8edb68a1a2c3b773 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:21:08 +0100 Subject: [PATCH 37/44] Fix tests - invocation is done via static methods --- .../InvokeBuiltinMethodViaInteropTest.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java index 62fc413cc6d0..e5773bda9c78 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java @@ -43,10 +43,19 @@ public void invokeGetMethodOnRef() { var interop = InteropLibrary.getUncached(); var refUnwrapped = ContextUtils.unwrapValue(ctx, ref); assertThat( - "Ref should have a 'get' method", - interop.isMemberInvocable(refUnwrapped, "get"), + "Ref builtin object should not have any members", + interop.hasMembers(refUnwrapped), + is(false)); + assertThat( + "Ref should have a meta-object (Ref type)", + interop.hasMetaObject(refUnwrapped), + is(true)); + var refMeta = interop.getMetaObject(refUnwrapped); + assertThat( + "Ref meta-object should have a 'get' method", + interop.isMemberInvocable(refMeta, "get"), is(true)); - var res = interop.invokeMember(refUnwrapped, "get"); + var res = interop.invokeMember(refMeta, "get", new Object[] {refMeta, refUnwrapped}); assertThat("Ref.get should return a number", interop.isNumber(res), is(true)); assertThat("Ref.get should return 42", interop.asInt(res), is(42)); return null; @@ -65,9 +74,10 @@ public void extensionMethodOnBuiltinTypeIsNotResolved() { () -> { var interop = InteropLibrary.getUncached(); var textUnwrapped = ContextUtils.unwrapValue(ctx, text); + var textMeta = interop.getMetaObject(textUnwrapped); assertThat( - "Text should not be able to resolve 'reverse' method", - interop.isMemberInvocable(textUnwrapped, "reverse"), + "Text type should not be able to resolve 'reverse' method", + interop.isMemberInvocable(textMeta, "reverse"), is(false)); return null; }); @@ -83,11 +93,12 @@ public void invokePlusOnTextWithParameter() { var interop = InteropLibrary.getUncached(); var text1Unwrapped = ContextUtils.unwrapValue(ctx, text1); var text2Unwrapped = ContextUtils.unwrapValue(ctx, text2); + var textMeta = interop.getMetaObject(text1Unwrapped); assertThat( - "Text should have a '+' method", - interop.isMemberInvocable(text1Unwrapped, "+"), + "Text type should have a '+' method", + interop.isMemberInvocable(textMeta, "+"), is(true)); - var res = interop.invokeMember(text1Unwrapped, "+", text2Unwrapped); + var res = interop.invokeMember(textMeta, "+", text1Unwrapped, text2Unwrapped); assertThat("Text.+ should return a text", interop.isString(res), is(true)); assertThat( "Text.+ should return 'FirstSecond'", interop.asString(res), is("FirstSecond")); From b21384a70e563bc2f60b1a69776c64ea75c612c6 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:21:30 +0100 Subject: [PATCH 38/44] Type.InvokeMember uses InvokeFunctionNode instead of UnresolvedSymbol --- .../enso/interpreter/runtime/data/Type.java | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java index 039ea8c8cc2d..8c0d878b62a9 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java @@ -4,7 +4,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.NeverDefault; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -24,9 +23,12 @@ import org.enso.interpreter.Constants; import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.node.ConstantNode; +import org.enso.interpreter.node.callable.InvokeCallableNode.ArgumentsExecutionMode; +import org.enso.interpreter.node.callable.InvokeCallableNode.DefaultsExecutionMode; +import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; +import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; import org.enso.interpreter.runtime.data.atom.AtomConstructor; @@ -385,20 +387,17 @@ boolean isMemberInvocable(String member) { @ExportMessage static final class InvokeMember { @Specialization( - guards = {"cachedMember.equals(member)"}, + guards = {"cachedMember.equals(member)", "func != null"}, limit = "3") static Object doCached( Type receiver, String member, Object[] args, @Cached("member") String cachedMember, - @Cached("buildSymbol(cachedMember)") UnresolvedSymbol cachedSymbol, - @CachedLibrary("cachedSymbol") InteropLibrary interop) + @Cached("findMethod(receiver, member)") Function func, + @Cached("buildInvokeFuncNode(func)") InvokeFunctionNode invokeFuncNode) throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - var argsForBuiltin = new Object[args.length + 1]; - argsForBuiltin[0] = receiver; - java.lang.System.arraycopy(args, 0, argsForBuiltin, 1, args.length); - return interop.execute(cachedSymbol, argsForBuiltin); + return invokeFuncNode.execute(func, null, null, args); } @Specialization(replaces = "doCached") @@ -407,20 +406,33 @@ static Object doUncached( String member, Object[] args, @CachedLibrary(limit = "3") InteropLibrary interop) - throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - var ctx = EnsoContext.get(interop); - var symbol = buildSymbol(member, ctx); - return doCached(receiver, member, args, member, symbol, interop); + throws UnsupportedMessageException, + UnsupportedTypeException, + ArityException, + UnknownIdentifierException { + var method = findMethod(receiver, member); + if (method == null) { + throw UnknownIdentifierException.create(member); + } + var invokeFuncNode = buildInvokeFuncNode(method); + return invokeFuncNode.execute(method, null, null, args); } - private static UnresolvedSymbol buildSymbol(String symbol, EnsoContext ctx) { - return UnresolvedSymbol.build(symbol, ctx.getBuiltins().getScope()); + static Function findMethod(Type receiver, String name) { + return receiver.methods().get(name); } - @NeverDefault - static UnresolvedSymbol buildSymbol(String symbol) { - var ctx = EnsoContext.get(null); - return buildSymbol(symbol, ctx); + static InvokeFunctionNode buildInvokeFuncNode(Function func) { + assert func != null; + var argumentInfos = func.getSchema().getArgumentInfos(); + var callArgInfos = new CallArgumentInfo[argumentInfos.length]; + for (var i = 0; i < argumentInfos.length; i++) { + var argInfo = argumentInfos[i]; + var callArgInfo = new CallArgumentInfo(argInfo.getName()); + callArgInfos[i] = callArgInfo; + } + return InvokeFunctionNode.build( + callArgInfos, DefaultsExecutionMode.EXECUTE, ArgumentsExecutionMode.EXECUTE); } } @@ -513,10 +525,4 @@ private static String simpleFuncName(Function func) { } return func.getName(); } - - /** - * @param simpleName Non-qualified name of the method. - * @param function The method. - */ - private record MethodWithName(String simpleName, Function function) {} } From 70a18c6be770a8743905a9c972a4e990f9028083 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:21:36 +0100 Subject: [PATCH 39/44] fmt --- .../test/builtins/BuiltinsJavaInteropTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java index 7f0d57b5d097..37f67763baa3 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java @@ -2,8 +2,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.containsString; import java.io.ByteArrayOutputStream; import org.enso.test.utils.ContextUtils; @@ -35,10 +33,11 @@ public void resetOutput() { @Test public void javaMethodAcceptsEnsoTimeOfDay_AsObject() { - var src = """ + var src = + """ from Standard.Base import Date_Time polyglot java import org.enso.example.PolyglotTestClass - + main = dt = Date_Time.now PolyglotTestClass.isPolyglotDate_Object dt @@ -49,10 +48,11 @@ public void javaMethodAcceptsEnsoTimeOfDay_AsObject() { @Test public void javaMethodAcceptsEnsoTimeOfDay_AsLocalDate() { - var src = """ + var src = + """ from Standard.Base import Date_Time polyglot java import org.enso.example.PolyglotTestClass - + main = dt = Date_Time.now PolyglotTestClass.isPolyglotDate_LocalDate dt @@ -63,10 +63,11 @@ public void javaMethodAcceptsEnsoTimeOfDay_AsLocalDate() { @Test public void javaMethodAcceptsEnsoTimeOfDay_AsValue() { - var src = """ + var src = + """ from Standard.Base import Date_Time polyglot java import org.enso.example.PolyglotTestClass - + main = dt = Date_Time.now PolyglotTestClass.isPolyglotDate_Value dt @@ -74,5 +75,4 @@ public void javaMethodAcceptsEnsoTimeOfDay_AsValue() { var result = ContextUtils.evalModule(ctx, src); assertThat(result.asBoolean(), is(true)); } - } From 3969177ef23276d111b06a79f749dd2c69e86869 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:29:41 +0100 Subject: [PATCH 40/44] Type.InvokeMember prepends receiver argument --- .../main/java/org/enso/interpreter/runtime/data/Type.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java index 8c0d878b62a9..83ce597d4dc1 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java @@ -397,7 +397,10 @@ static Object doCached( @Cached("findMethod(receiver, member)") Function func, @Cached("buildInvokeFuncNode(func)") InvokeFunctionNode invokeFuncNode) throws UnsupportedMessageException, UnsupportedTypeException, ArityException { - return invokeFuncNode.execute(func, null, null, args); + var argsWithReceiver = new Object[args.length + 1]; + argsWithReceiver[0] = receiver; + System.arraycopy(args, 0, argsWithReceiver, 1, args.length); + return invokeFuncNode.execute(func, null, null, argsWithReceiver); } @Specialization(replaces = "doCached") @@ -415,7 +418,7 @@ static Object doUncached( throw UnknownIdentifierException.create(member); } var invokeFuncNode = buildInvokeFuncNode(method); - return invokeFuncNode.execute(method, null, null, args); + return doCached(receiver, member, args, member, method, invokeFuncNode); } static Function findMethod(Type receiver, String name) { From a001eab85d27c8751035865c5688971896c31009 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:29:49 +0100 Subject: [PATCH 41/44] Test invocation of File.path --- .../InvokeBuiltinMethodViaInteropTest.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java index e5773bda9c78..46e401353ab1 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java @@ -2,6 +2,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import com.oracle.truffle.api.interop.InteropLibrary; import org.enso.test.utils.ContextUtils; @@ -55,13 +56,36 @@ public void invokeGetMethodOnRef() { "Ref meta-object should have a 'get' method", interop.isMemberInvocable(refMeta, "get"), is(true)); - var res = interop.invokeMember(refMeta, "get", new Object[] {refMeta, refUnwrapped}); + var res = interop.invokeMember(refMeta, "get", new Object[] {refUnwrapped}); assertThat("Ref.get should return a number", interop.isNumber(res), is(true)); assertThat("Ref.get should return 42", interop.asInt(res), is(42)); return null; }); } + @Test + public void invokePathMethodOnFile() { + var code = + """ + from Standard.Base import File + + main = + File.current_directory + """; + var file = ContextUtils.evalModule(ctx, code); + ContextUtils.executeInContext( + ctx, + () -> { + var fileType = file.getMetaObject(); + assertThat(fileType, is(notNullValue())); + assertThat(fileType.hasMember("path"), is(true)); + var res = fileType.invokeMember("path", new Object[] {file}); + assertThat("path method can be invoked", res, is(notNullValue())); + assertThat("path method returns correct result", res.isString(), is(true)); + return null; + }); + } + /** * 'Text.reverse' is an extension method defined outside builtins module scope, so it cannot be * resolved. From def1f6b7247bebf2060f1a833c6b9cf43d24b868 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:31:41 +0100 Subject: [PATCH 42/44] Test invocation of Vector.to_text --- .../InvokeBuiltinMethodViaInteropTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java index 46e401353ab1..48285ea4c4c6 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/InvokeBuiltinMethodViaInteropTest.java @@ -86,6 +86,25 @@ public void invokePathMethodOnFile() { }); } + @Test + public void invokeToTextOnVector() { + var code = """ + main = [1,2,3] + """; + var vec = ContextUtils.evalModule(ctx, code); + ContextUtils.executeInContext( + ctx, + () -> { + var vecType = vec.getMetaObject(); + assertThat(vecType, is(notNullValue())); + assertThat(vecType.hasMember("to_text"), is(true)); + var res = vecType.invokeMember("to_text", new Object[] {vec}); + assertThat("to_text method can be invoked", res, is(notNullValue())); + assertThat("to_text method returns correct result", res.isString(), is(true)); + return null; + }); + } + /** * 'Text.reverse' is an extension method defined outside builtins module scope, so it cannot be * resolved. From eb125ba350e8aa7faa343d65d52dcecdd7890a2d Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Thu, 12 Dec 2024 19:44:11 +0100 Subject: [PATCH 43/44] Method fetching is done behind truffle boundary --- .../src/main/java/org/enso/interpreter/runtime/data/Type.java | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java index 83ce597d4dc1..32f4646ca782 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Type.java @@ -495,6 +495,7 @@ private boolean isNothing(Node lib) { private Map methods() { if (methods == null) { + CompilerDirectives.transferToInterpreter(); var allMethods = new HashMap(); var defScope = definitionScope.asModuleScope(); var methodsFromThisScope = defScope.getMethodsForType(this); From 0b5758caa51476f22546228b8ee7eaf2473087a7 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Fri, 13 Dec 2024 12:10:23 +0100 Subject: [PATCH 44/44] Reassigning @CompilationFinal field should deoptimize --- .../org/enso/interpreter/runtime/builtin/BuiltinObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java index 26051817c7e2..e49a23a12a88 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -48,7 +48,7 @@ public final boolean hasType() { @ExportMessage public final Type getType(@Bind("$node") Node node) { if (cachedBuiltinType == null) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); var ctx = EnsoContext.get(node); cachedBuiltinType = ctx.getBuiltins().getBuiltinType(builtinName); }