From 0505b69c6fa6a43b4e5df59aebebeb4c116ada32 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Sun, 15 Jun 2014 10:24:57 -0700
Subject: [PATCH] eval bug fixes; printing for language is.language types;
 sys.source("file", globalenv()) working now" assert promise ony evaluated
 once RLanguage and RPromise siblings not subclasses; add RLanguageRep as
 parent

---
 .../oracle/truffle/r/nodes/RProxyNode.java    |  1 +
 .../r/nodes/access/AccessArrayNode.java       |  5 +++
 .../r/nodes/builtin/RBuiltinRootNode.java     |  2 +-
 .../r/nodes/builtin/base/EvalFunctions.java   |  4 +-
 .../r/nodes/builtin/base/Expression.java      | 19 +++++++--
 .../truffle/r/nodes/builtin/base/OnExit.java  |  2 +-
 .../nodes/builtin/base/PrettyPrinterNode.java | 40 ++++++++++++++++---
 .../truffle/r/nodes/builtin/base/Quote.java   |  4 +-
 .../truffle/r/nodes/function/PromiseNode.java | 18 ++++++---
 .../truffle/r/nodes/function/RCallNode.java   |  4 +-
 .../truffle/r/runtime/data/RLanguage.java     | 12 ++----
 .../truffle/r/runtime/data/RPromise.java      |  6 ++-
 12 files changed, 84 insertions(+), 33 deletions(-)

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 77e518bfc4..c480128296 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 47dd4ea7b7..8796155674 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 95f1597a51..4f746cd197 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 ab281cd796..b9ba5beeb8 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 10c7b25f54..8454a750c3 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 15de467902..14749648d7 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 5f05cac3ed..f854294286 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 e98994c032..d4d50e99ba 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 d4abcf6d0e..6a6fcdc898 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 0c45092a06..3f25f90ef5 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 5400bcbeb4..6cddc5bf77 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 cb8ee36813..b1244a0a25 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;
     }
-- 
GitLab