diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java index 77e518bfc4f8f328562d0a1266178bd7f1f07346..c480128296fc57c1a9b9a3643de96d2710b9a54d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RProxyNode.java @@ -252,6 +252,7 @@ public abstract class RProxyNode extends RNode { return (RSymbol) proxyScalar(x); } + @Specialization public RLanguage wrap(RLanguage x) { return proxy(x); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArrayNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArrayNode.java index 47dd4ea7b77332ba3fe8d886734d962b92371814..8796155674fdc4754b27023b6cc24ad476cc4b15 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArrayNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArrayNode.java @@ -1312,6 +1312,11 @@ public abstract class AccessArrayNode extends RNode { throw RError.getGenericError(getEncapsulatingSourceSection(), "data frames subset access not supported"); } + @Specialization(order = 1010) + Object access(VirtualFrame frame, RExpression expression, int recLevel, int position, RAbstractLogicalVector dropDim) { + return accessRecursive(frame, expression.getList(), position, recLevel, dropDim); + } + protected boolean outOfBounds(RList vector, @SuppressWarnings("unused") int recLevel, int position) { return position > vector.getLength(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java index 95f1597a512a919c22f03013bf6df03971fe8856..4f746cd197605cf5672528a3573abfd7bbe65d73 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java @@ -53,7 +53,7 @@ public final class RBuiltinRootNode extends RRootNode { return rBuiltin == null || rBuiltin.nonEvalArgs().length == 0; } - public boolean evalArg(int index) { + public boolean evaluatesArg(int index) { RBuiltin rBuiltin = builtin.getRBuiltin(); if (rBuiltin == null) { return true; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java index ab281cd7961e6302d837d752fca32a324dc4e5bc..b9ba5beeb8e67052b3f8d3ad1ac687507d47bd4a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java @@ -127,7 +127,7 @@ public class EvalFunctions { * evalq does not evaluate it's first argument */ controlVisibility(); - return doEvalBody(expr, envir, enclos); + return doEvalBody(RDataFactory.createLanguage(expr.getRep()), envir, enclos); } } @@ -157,7 +157,7 @@ public class EvalFunctions { * local does not evaluate it's first argument */ controlVisibility(); - return doEvalBody(expr, envir, enclos); + return doEvalBody(RDataFactory.createLanguage(expr.getRep()), envir, enclos); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java index 10c7b25f541b467f89608124fe888dff03fed118..8454a750c3e1e018165169706e06f9e2036b18e0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java @@ -38,16 +38,29 @@ public abstract class Expression extends RBuiltinNode { return PARAMETER_NAMES; } + /* + * Owing to the nonEvalArgs, all arguments are RPromise, but an expression actually consists of + * RLanguage elements so we convert, even though an RPromise is a subclass. + */ + @Specialization public Object doExpression(Object[] args) { - RList list = RDataFactory.createList(args); + RLanguage[] data = new RLanguage[args.length]; + for (int i = 0; i < args.length; i++) { + data[i] = convert((RPromise) args[i]); + } + RList list = RDataFactory.createList(data); return RDataFactory.createExpression(list); } @Specialization - public Object doExpression(RLanguage language) { - RList list = RDataFactory.createList(new Object[]{language}); + public Object doExpression(RPromise language) { + RList list = RDataFactory.createList(new Object[]{convert(language)}); return RDataFactory.createExpression(list); } + private static RLanguage convert(RPromise promise) { + return RDataFactory.createLanguage(promise.getRep()); + } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java index 15de4679025f9af8db0bb0b5ed61cc9f743f2aa2..14749648d7c299bd02c55b197ae7a0a547205135 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java @@ -52,7 +52,7 @@ public abstract class OnExit extends RInvisibleBuiltinNode { } @Specialization - public Object onExit(@SuppressWarnings("unused") RLanguage expr, @SuppressWarnings("unused") RLanguage add) { + public Object onExit(@SuppressWarnings("unused") RPromise expr, @SuppressWarnings("unused") byte add) { controlVisibility(); RContext.getInstance().setEvalWarning("on.exit ignored"); return RNull.instance; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java index 5f05cac3edea1e410a817b3449396c4dd0e78903..f854294286c9080e878200b85a0c053dfd8d851d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java @@ -198,8 +198,17 @@ public abstract class PrettyPrinterNode extends RNode { @Specialization(order = 80) public String prettyPrint(VirtualFrame frame, RExpression expr, Object listElementName) { - // TODO extract source of the elements - return "expression"; + StringBuilder builder = new StringBuilder(); + builder.append("expression("); + RList exprs = expr.getList(); + for (int i = 0; i < exprs.getLength(); i++) { + if (i != 0) { + builder.append(", "); + } + builder.append(prettyPrintLanguageRep((RLanguage) exprs.getDataAt(i), listElementName)); + } + builder.append(')'); + return builderToString(builder); } @Specialization(order = 85) @@ -208,9 +217,19 @@ public abstract class PrettyPrinterNode extends RNode { } @Specialization(order = 86) - public String prettyPrint(VirtualFrame frame, RLanguage expr, Object listElementName) { - // TODO extract source of the element - return "language element"; + public String prettyPrintPromise(VirtualFrame frame, RPromise promise, Object listElementName) { + return prettyPrintLanguageRep(promise, listElementName); + } + + @Specialization(order = 87) + public String prettyPrintLanguage(VirtualFrame frame, RLanguage language, Object listElementName) { + return prettyPrintLanguageRep(language, listElementName); + } + + public String prettyPrintLanguageRep(RLanguageRep languageRep, Object listElementName) { + RNode node = (RNode) languageRep.getRep(); + String s = node.getSourceSection().getCode(); + return s; } private String printAttributes(VirtualFrame frame, RAbstractVector vector, RAttributes attributes) { @@ -893,6 +912,17 @@ public abstract class PrettyPrinterNode extends RNode { public String prettyPrintListElement(VirtualFrame frame, RAbstractVector operand, Object listElementName) { return prettyPrintSingleElement(frame, operand, listElementName); } + + @Specialization + public String prettyPrintListElement(VirtualFrame frame, RSymbol operand, Object listElementName) { + return prettyPrintSingleElement(frame, operand, listElementName); + } + + @Specialization + public String prettyPrintListElement(VirtualFrame frame, RLanguage operand, Object listElementName) { + return prettyPrintSingleElement(frame, operand, listElementName); + } + } @NodeChild(value = "operand", type = RNode.class) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java index e98994c03271f769f248535015dac971c46ea000..d4d50e99ba7aac1bd7df8d1f228b1f6036a527d7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java @@ -51,8 +51,8 @@ public abstract class Quote extends RBuiltinNode { } @Specialization - public RLanguage doQuote(RLanguage arg) { + public RLanguage doQuote(RPromise arg) { controlVisibility(); - return arg; + return RDataFactory.createLanguage(arg.getRep()); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java index d4abcf6d0e93ad0ff0e6d419030531005c41fca7..6a6fcdc898e150df98859a6c3e9ebe74637b6abf 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java @@ -23,23 +23,29 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.runtime.data.*; public final class PromiseNode extends RNode { - RPromise promise; + RLanguageRep languageRep; - private PromiseNode(RPromise promise) { - this.promise = promise; + private PromiseNode(RLanguageRep languageRep) { + this.languageRep = languageRep; } - public static PromiseNode create(RPromise promise) { - return new PromiseNode(promise); + public static PromiseNode create(SourceSection src, RLanguageRep language) { + PromiseNode pn = new PromiseNode(language); + pn.assignSourceSection(src); + return pn; } + /** + * {@link RPromise} values are assign once. + */ @Override public Object execute(VirtualFrame frame) { - return promise; + return new RPromise(languageRep.getRep()); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 0c45092a06004000ff76b851f60eb30420daedaa..3f25f90ef5923aa9d45180eb31532d6df2c8b963 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -293,8 +293,8 @@ public abstract class RCallNode extends RNode { } private static RNode checkPromise(RBuiltinRootNode builtinRootNode, RNode argNode, int lix) { - if (!builtinRootNode.evalArg(lix)) { - return PromiseNode.create(new RPromise(argNode)); + if (!builtinRootNode.evaluatesArg(lix)) { + return PromiseNode.create(argNode.getSourceSection(), new RLanguageRep(argNode)); } else { return argNode; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java index 5400bcbeb4e977668a8a3c2edcd0e607b32b9b20..6cddc5bf77f566435edabbf6e45c8acbea073cd6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java @@ -23,19 +23,13 @@ package com.oracle.truffle.r.runtime.data; /** - * Denotes an (unevaluated) element of, e.g. an {@link RExpression}. The representation is not - * disclosed here, owing partly to import circularities, but it will typically be an {@code RNode} - * that captures the (unevaluated) AST for the element. + * Denotes an (unevaluated) element of, e.g. an {@link RExpression}. */ @com.oracle.truffle.api.CompilerDirectives.ValueType -public class RLanguage { - private final Object rep; +public class RLanguage extends RLanguageRep { public RLanguage(Object rep) { - this.rep = rep; + super(rep); } - public Object getRep() { - return rep; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java index cb8ee3681354100adad6542c31113cec05e0b493..b1244a0a25ee37357312b674114855636fbd2180 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java @@ -23,10 +23,10 @@ package com.oracle.truffle.r.runtime.data; /** - * Denotes an R {@code promise}. It extends {@link RLanguage} with a (lazily) evaluated value. + * Denotes an R {@code promise}. It extends {@link RLanguageRep} with a (lazily) evaluated value. */ @com.oracle.truffle.api.CompilerDirectives.ValueType -public class RPromise extends RLanguage { +public class RPromise extends RLanguageRep { /** * Denotes a promise that raised an error during evaluation. */ @@ -52,6 +52,8 @@ public class RPromise extends RLanguage { } else { this.value = newValue; } + } else { + assert false : "promise already has a value"; } return this.value; }