Skip to content
Snippets Groups Projects
Commit e1b4fd3d authored by Florian Angerer's avatar Florian Angerer
Browse files

Changed interop behavior of promises.

parent a8659ed6
No related branches found
No related tags found
No related merge requests found
......@@ -22,40 +22,125 @@
*/
package com.oracle.truffle.r.engine.interop;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.CanResolve;
import com.oracle.truffle.api.interop.MessageResolution;
import com.oracle.truffle.api.interop.Resolve;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RPromise;
@MessageResolution(receiverType = RPromise.class)
public class RPromiseMR {
private static final String PROP_VALUE = "value";
private static final String PROP_IS_EVALUATED = "isEvaluated";
private static final String PROP_IS_EAGER = "isEager";
@Resolve(message = "IS_BOXED")
public abstract static class RPromiseIsBoxedNode extends Node {
protected Object access(@SuppressWarnings("unused") RPromise receiver) {
return true;
return false;
}
}
@Resolve(message = "HAS_SIZE")
public abstract static class RPromiseHasSizeNode extends Node {
@Resolve(message = "IS_NULL")
public abstract static class RPromiseIsNullNode extends Node {
protected Object access(@SuppressWarnings("unused") RPromise receiver) {
return false;
}
}
@Resolve(message = "IS_NULL")
public abstract static class RPromiseIsNullNode extends Node {
@Resolve(message = "READ")
public abstract static class RPromiseReadNode extends Node {
protected Object access(@SuppressWarnings("unused") VirtualFrame frame, RPromise receiver, String field) {
if (PROP_IS_EAGER.equals(field)) {
return RRuntime.asLogical(RPromise.PromiseState.isEager(receiver.getState()));
}
if (PROP_IS_EVALUATED.equals(field)) {
return RRuntime.asLogical(receiver.isEvaluated());
}
if (PROP_VALUE.equals(field)) {
// only read value if evaluated
if (receiver.isEvaluated()) {
return receiver.getValue();
}
return RNull.instance;
}
throw UnknownIdentifierException.raise(field);
}
}
@Resolve(message = "WRITE")
public abstract static class RPromiseWriteNode extends Node {
@SuppressWarnings("try")
protected Object access(@SuppressWarnings("unused") VirtualFrame frame, RPromise receiver, String field, Object valueObj) {
if (PROP_IS_EVALUATED.equals(field)) {
if (!(valueObj instanceof Boolean)) {
throw UnsupportedTypeException.raise(new Object[]{valueObj});
}
boolean newVal = (boolean) valueObj;
if (!receiver.isEvaluated() && newVal) {
try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
PromiseHelperNode.evaluateSlowPath(receiver);
}
} else if (receiver.isEvaluated() && !newVal) {
try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
receiver.resetValue();
}
}
return RRuntime.asLogical(receiver.isEvaluated());
}
throw UnknownIdentifierException.raise(field);
}
}
@Resolve(message = "KEYS")
public abstract static class RPromiseKeysNode extends Node {
protected Object access(@SuppressWarnings("unused") RPromise receiver) {
return false;
return RDataFactory.createStringVector(new String[]{PROP_VALUE, PROP_IS_EVALUATED, PROP_IS_EAGER}, true);
}
}
@Resolve(message = "KEY_INFO")
public abstract static class RPromiseKeyInfoNode extends Node {
private static final int READABLE = 1 << 1;
private static final int WRITABLE = 1 << 2;
@SuppressWarnings("try")
protected Object access(@SuppressWarnings("unused") VirtualFrame frame, @SuppressWarnings("unused") RPromise receiver, String identifier) {
if (PROP_IS_EAGER.equals(identifier) || PROP_VALUE.equals(identifier)) {
return READABLE;
}
if (PROP_IS_EVALUATED.equals(identifier)) {
return READABLE + WRITABLE;
}
return 0;
}
}
@Resolve(message = "UNBOX")
public abstract static class RPromiseUnboxNode extends Node {
@Resolve(message = "TO_NATIVE")
public abstract static class RPromiseToNativeNode extends Node {
protected Object access(RPromise receiver) {
return receiver.getValue();
return new NativePointer(receiver);
}
}
......
......@@ -203,6 +203,16 @@ public class RPromise implements RTypedValue {
return value;
}
/**
* Discards any previously evaluated value if this is not an eager promise.
*/
public final void resetValue() {
// Only non-eager promises can be reset.
if (!PromiseState.isEager(state)) {
value = null;
}
}
/**
* Used in case the {@link RPromise} is evaluated outside.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment