Skip to content

Commit

Permalink
Converting to Date atom as late as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
JaroslavTulach committed Apr 9, 2022
1 parent c57941b commit 87cf546
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.enso.interpreter.node.callable;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
Expand All @@ -12,17 +13,20 @@
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.locks.Lock;

import org.enso.interpreter.Language;
import org.enso.interpreter.node.BaseNode;
import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode;
import org.enso.interpreter.node.callable.resolver.*;
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.ArrayRope;
import org.enso.interpreter.runtime.data.text.Text;
Expand All @@ -34,7 +38,6 @@
public abstract class InvokeMethodNode extends BaseNode {
private @Child InvokeFunctionNode invokeFunctionNode;
private final ConditionProfile errorReceiverProfile = ConditionProfile.createCountingProfile();
private final BranchProfile polyglotArgumentErrorProfile = BranchProfile.create();
private @Child InvokeMethodNode childDispatch;
private final int argumentCount;
private final int thisArgumentPosition;
Expand Down Expand Up @@ -162,8 +165,7 @@ Stateful doWarning(
guards = {
"!methods.hasFunctionalDispatch(_this)",
"!methods.hasSpecialDispatch(_this)",
"polyglotCallType != NOT_SUPPORTED",
"polyglotCallType != CONVERT_TO_TEXT"
"polyglotCallType.isInteropLibrary()",
})
Stateful doPolyglot(
VirtualFrame frame,
Expand Down Expand Up @@ -235,6 +237,53 @@ Stateful doConvertText(
}
}

@Specialization(
guards = {
"!methods.hasFunctionalDispatch(_this)",
"!methods.hasSpecialDispatch(_this)",
"getPolyglotCallType(_this, symbol.getName(), interop) == CONVERT_TO_DATE"
})
Stateful doConvertDate(
VirtualFrame frame,
Object state,
UnresolvedSymbol symbol,
Object _this,
Object[] arguments,
@CachedLibrary(limit = "10") MethodDispatchLibrary methods,
@CachedLibrary(limit = "1") MethodDispatchLibrary dateDispatch,
@CachedLibrary(limit = "10") InteropLibrary interop,
@Cached("wrapDateInAtom(interop)") java.util.function.Function<Object,Atom> wrapDate
) {
try {
Atom date = wrapDate.apply(_this);
Function function = dateDispatch.getFunctionalDispatch(date, symbol);
arguments[0] = date;
return invokeFunctionNode.execute(function, frame, state, arguments);
} catch (MethodDispatchLibrary.NoSuchMethodException e) {
throw new PanicException(
Context.get(this).getBuiltins().error().makeNoSuchMethodError(_this, symbol), this);
}
}

final java.util.function.Function<Object,Atom> wrapDateInAtom(InteropLibrary iop) {
CompilerAsserts.neverPartOfCompilation();
final Context ctx = Context.get(this);
ctx.ensureModuleIsLoaded("Standard.Base.Data.Time.Date");
Optional<Module> dateModule = ctx.findModule("Standard.Base.Data.Time.Date");
if (dateModule.isPresent()) {
try {
Object constrDate = iop.invokeMember(dateModule.get(), "get_constructor", "Date");
if (constrDate instanceof AtomConstructor) {
AtomConstructor c = (AtomConstructor) constrDate;
return c::newInstance;
}
} catch (InteropException ex) {
throw new IllegalStateException("Impossible, _this is guaranteed to be a string.");
}
}
return null;
}

@Specialization(
guards = {
"!methods.hasFunctionalDispatch(_this)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,25 @@ public enum PolyglotCallType {
* org.enso.interpreter.runtime.data.text.Text} and dispatching natively.
*/
CONVERT_TO_TEXT,
/**
* The method call should be handled by converting {@code _this} to a {@code
* Standard.Base.Data.Time.Date} and dispatching natively.
*/
CONVERT_TO_DATE,
/** The method call should be handled by dispatching through the {@code Any} type. */
NOT_SUPPORTED
NOT_SUPPORTED;

/**
* Directly use {@link InteropLibrary}, or not. Types that return false are
* either {@link #NOT_SUPPORTED unsupported} or require
* additional conversions like {@link #CONVERT_TO_TEXT} and {@link #CONVERT_TO_DATE}.
*
* @return true if one can directly pass this object to
* {@link InteropLibrary}
*/
public boolean isInteropLibrary() {
return this != NOT_SUPPORTED && this != CONVERT_TO_TEXT && this != CONVERT_TO_DATE;
}
}

private static final String ARRAY_LENGTH_NAME = "length";
Expand Down Expand Up @@ -76,9 +93,12 @@ public static PolyglotCallType getPolyglotCallType(
return PolyglotCallType.READ_ARRAY_ELEMENT;
} else if (library.isString(_this)) {
return PolyglotCallType.CONVERT_TO_TEXT;
} else {
return PolyglotCallType.NOT_SUPPORTED;
} else if (library.isDate(_this)) {
if (!library.isTime(_this)) {
return PolyglotCallType.CONVERT_TO_DATE;
}
}
return PolyglotCallType.NOT_SUPPORTED;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,36 +76,6 @@ Atom doNull(

@Fallback
Object doOther(Object o, @CachedLibrary(limit = "3") InteropLibrary dates) {
if (o instanceof Atom) {
return o;
}
if (dates.isDate(o) && !dates.isTime(o)) {
o = convertToStandardBaseDataTimeDate(dates, o);
}
return o;
}

private static Object convertToStandardBaseDataTimeDate(InteropLibrary dates, Object o) {
CompilerAsserts.neverPartOfCompilation();
final Context ctx = Context.get(dates);
final InteropLibrary iop = InteropLibrary.getUncached();
ctx.ensureModuleIsLoaded("Standard.Base.Data.Time.Date");
Optional<Module> dateModule = ctx.findModule("Standard.Base.Data.Time.Date");
if (!dateModule.isPresent()) {
return o;
}
try {
Object constrDate = iop.invokeMember(dateModule.get(), "get_constructor", "Date");
if (constrDate instanceof AtomConstructor) {
AtomConstructor c = (AtomConstructor) constrDate;
final LocalDate maybeDate = iop.asDate(o);
if (maybeDate instanceof LocalDate) {
return c.newInstance(o);
}
}
return o;
} catch (InteropException ex) {
return o;
}
}
}

0 comments on commit 87cf546

Please sign in to comment.