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..1118c5a73cd7 --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/example/PolyglotTestClass.java @@ -0,0 +1,20 @@ +package org.enso.example; + +import java.time.LocalDate; +import org.graalvm.polyglot.Value; + +public final class PolyglotTestClass { + private 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..06b15f606dec --- /dev/null +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/builtins/BuiltinsJavaInteropTest.java @@ -0,0 +1,88 @@ +package org.enso.interpreter.test.builtins; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +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; + +/** + * In these tests, we call Java methods from Enso. Java methods have different signatures that + * accept Enso values in different ways. + */ +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(); + } + + /** + * This test reflects the state of many Java methods in stdlibs that accept Enso values as {@link + * java.lang.Object}. If the Java method has a single argument of type {@link java.lang.Object}, + * and we pass {@code Date_Time} in it, we expect the host interop conversion to convert it to + * {@link java.time.LocalDateTime}. + */ + @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)); + } +} 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 new file mode 100644 index 000000000000..3c3693d0660d --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/BuiltinObject.java @@ -0,0 +1,111 @@ +package org.enso.interpreter.runtime.builtin; + +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.Idempotent; +import com.oracle.truffle.api.dsl.Specialization; +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 org.enso.interpreter.node.expression.builtin.Builtin; +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; + +/** + * Base class for every Enso builtin object. Not type. Note that base class for a builtin type is + * {@link Builtin}. + * + *

In other words, this class represents an object of builtin type in a similar way that {@link + * org.enso.interpreter.runtime.data.atom.Atom} represents an object of a non-builtin type. + */ +@ExportLibrary(InteropLibrary.class) +@ExportLibrary(TypesLibrary.class) +public abstract class BuiltinObject extends EnsoObject { + + @ExportMessage + public final boolean hasType() { + return true; + } + + /** + * Returns the name of the builtin as saved inside {@link Builtins#builtinsByName}. Not fully + * qualified. + * + * @return + */ + protected abstract String builtinName(); + + protected final Type getBuiltinType(Node node) { + return GetType.uncached(this, node); + } + + /** + * 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 hasMembers() { + return false; + } + + @ExportMessage + public final Object getMembers(boolean includeInternal) throws UnsupportedMessageException { + throw UnsupportedMessageException.create(); + } + + @ExportMessage + public final boolean hasMetaObject() { + return true; + } + + @ExportMessage(name = "getType", library = TypesLibrary.class) + @ExportMessage(name = "getMetaObject", library = InteropLibrary.class) + public static final class GetType { + + GetType() {} + + /** + * Caching on class of the receiver - as long as there is the same class, its {@link + * #builtinName()} method will return the same value. Note that we don't want to cache on the + * builtin name, as that would create a separate polymorph cache for every instance of the + * receiver. + */ + @Specialization( + guards = {"cachedReceiverClass == receiver.getClass()", "getCtx(node) == cachedCtx"}, + limit = "1") + public static Type doItCached( + BuiltinObject receiver, + @Bind("$node") Node node, + @Cached("receiver.getClass()") Class cachedReceiverClass, + @Cached(value = "getCtx(node)", allowUncached = true) EnsoContext cachedCtx, + @Cached(value = "getBuiltinType(receiver, cachedCtx)", allowUncached = true) + Builtin cachedBuiltinType) { + return cachedBuiltinType.getType(); + } + + @Specialization(replaces = "doItCached") + public static Type uncached(BuiltinObject receiver, @Bind("$node") Node node) { + var ctx = getCtx(node); + return getBuiltinType(receiver, ctx).getType(); + } + + @TruffleBoundary + public static Builtin getBuiltinType(BuiltinObject receiver, EnsoContext ctx) { + return ctx.getBuiltins().getBuiltinType(receiver.builtinName()); + } + + @Idempotent + public static EnsoContext getCtx(Node node) { + return EnsoContext.get(node); + } + } +} 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..1c7872096879 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,30 +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.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.runtime.library.dispatch.TypesLibrary; +import org.enso.interpreter.runtime.builtin.BuiltinObject; 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) { this.date = date; } + @Override + protected String builtinName() { + return "Date"; + } + @Builtin.Method(description = "Return current Date", autoRegister = false) @CompilerDirectives.TruffleBoundary public static EnsoDate today() { @@ -77,26 +78,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..e9f1ccc2c710 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,37 +1,37 @@ 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.runtime.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) { this.dateTime = dateTime; } + @Override + protected String builtinName() { + return "Date_Time"; + } + @Builtin.Method( name = "epoch_start", description = "Return the Enso start of the Epoch", @@ -205,26 +205,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..d96397962d05 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; @@ -16,37 +14,21 @@ import java.time.temporal.Temporal; import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; 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) { 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; + @Override + protected String builtinName() { + return "Duration"; } @Builtin.Method( 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..335cd65d4ff4 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; @@ -38,22 +37,22 @@ import java.util.function.Function; import org.enso.interpreter.dsl.Builtin; 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; 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) { @@ -63,6 +62,11 @@ public EnsoFile(TruffleFile truffleFile) { this.truffleFile = truffleFile; } + @Override + protected String builtinName() { + return "File"; + } + @Builtin.Method(name = "output_stream_builtin") @Builtin.WrapException(from = IOException.class) @Builtin.Specialize @@ -797,26 +801,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..331849c5f938 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,34 +2,36 @@ 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.runtime.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) { this.localTime = localTime; } + @Override + protected String builtinName() { + return "Time_Of_Day"; + } + @Builtin.Method( name = "new_builtin", description = "Constructs a new Time_OF_Day from an hour", @@ -143,26 +145,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..5c29c4e5e70d 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,35 +2,37 @@ 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.runtime.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) { this.zone = zone; } + @Override + protected String builtinName() { + return "Time_Zone"; + } + @Builtin.Method(description = "Get the unique identifier for your system's current timezone.") @CompilerDirectives.TruffleBoundary public Text zoneId() { @@ -100,24 +102,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..f5d3d5cffd88 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 @@ -10,8 +10,8 @@ import java.lang.ref.PhantomReference; import org.enso.interpreter.dsl.Builtin; import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.builtin.BuiltinObject; 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; @@ -54,6 +53,11 @@ public ManagedResource( this.phantomReference = factory.apply(this); } + @Override + protected String builtinName() { + return "Managed_Resource"; + } + /** * @return the underlying resource */ @@ -97,30 +101,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 = getBuiltinType(node); return type.getName() + " " + InteropLibrary.getUncached().toDisplayString(resource, allowSideEffects); 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..f25c510dee59 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,23 +1,24 @@ 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.runtime.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; + @Override + protected String builtinName() { + return "Ref"; + } + /** * Creates a new reference. * @@ -51,26 +52,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) { 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 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..bb9cfef1924c 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.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.builtin.BuiltinObject; 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; @@ -57,6 +52,11 @@ static EnsoHashMap createEmpty() { return new EnsoHashMap(EnsoHashMapBuilder.create()); } + @Override + protected String builtinName() { + return "Dictionary"; + } + EnsoHashMapBuilder getMapBuilder( VirtualFrame frame, boolean readOnly, HashCodeNode hashCodeNode, EqualsNode equalsNode) { if (readOnly) { @@ -144,26 +144,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/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java index 7ae2fac6fbc1..4bfabb1b33f8 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; @@ -16,16 +14,12 @@ import java.util.concurrent.locks.ReentrantLock; import org.enso.interpreter.dsl.Builtin; 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.interpreter.runtime.builtin.BuiltinObject; 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; @@ -46,6 +40,11 @@ private Text(ConcatRope contents) { this.contents = contents; } + @Override + protected String builtinName() { + return "Text"; + } + @Builtin.Method( description = """ @@ -212,16 +211,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 +234,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. * 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..09ef29401c5a 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.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; +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; 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. */ @@ -78,6 +73,11 @@ final Object[] getItems() { return items; } + @Override + protected String builtinName() { + return "Array"; + } + /** * Marks the object as array-like for Polyglot APIs. * @@ -159,27 +159,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 +291,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..8a54ad68aad8 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,13 +5,20 @@ import com.oracle.truffle.api.library.CachedLibrary; import java.nio.ByteBuffer; import org.enso.interpreter.dsl.Builtin; +import org.enso.interpreter.runtime.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 { +public final class ArrayLikeHelpers extends BuiltinObject { + private ArrayLikeHelpers() {} + @Override + protected String builtinName() { + return "Array_Like_Helpers"; + } + @Builtin.Method( name = "new_array_proxy_builtin", description = "Creates an array backed by a proxy object.") @@ -121,4 +128,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/ArrayProxy.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/ArrayProxy.java index 0aca184e7e45..be94c9e0430f 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.runtime.builtin.BuiltinObject; /** * A wrapper that allows to turn an Enso callback providing elements into a polyglot Array. @@ -27,9 +22,8 @@ * 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; @@ -44,6 +38,11 @@ static ArrayProxy create(long length, Object at) { return new ArrayProxy(length, at); } + @Override + protected String builtinName() { + return "Array"; + } + @ExportMessage public boolean hasArrayElements() { return true; @@ -83,29 +82,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(); - } } 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..2fad7a282ae8 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,26 @@ 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.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.builtin.BuiltinObject; 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]); + @Override + protected String builtinName() { + return "Vector"; + } + @ExportMessage boolean hasArrayElements() { return true; @@ -78,30 +78,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/number/EnsoBigInteger.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java index 961d31e88027..2e7892b34a9f 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.runtime.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; /** @@ -37,6 +30,11 @@ public BigInteger getValue() { return value; } + @Override + protected String builtinName() { + return "Integer"; + } + @Override @CompilerDirectives.TruffleBoundary public String toString() { @@ -125,26 +123,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) { 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..14ede3705e1c 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,26 +2,21 @@ 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.runtime.EnsoContext; -import org.enso.interpreter.runtime.data.EnsoObject; -import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.builtin.BuiltinObject; 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; @@ -32,6 +27,11 @@ private Warning(Object value, Object origin, long sequenceId) { this.sequenceId = sequenceId; } + @Override + protected String builtinName() { + return "Warning"; + } + @Builtin.Method(name = "value", description = "Gets the payload of the warning.") @SuppressWarnings("generic-enso-builtin-type") public Object getValue() { @@ -129,16 +129,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(); 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..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 @@ -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.runtime.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",