diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AnyVectorToStringVectorWriter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AnyVectorToStringVectorWriter.java
index 5282e1d86e05f9d9fda1a0aec8f1c9a7bba188e0..c3c58869de499c385be2b8630a20ac6d3407cec4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AnyVectorToStringVectorWriter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AnyVectorToStringVectorWriter.java
@@ -71,14 +71,14 @@ public class AnyVectorToStringVectorWriter extends Writer implements PrettyWrite
     }
 
     @Override
-    public void beginElement(@SuppressWarnings("hiding") RAbstractVector vector, int index, FormatMetrics fm) {
+    public void beginElement(int index, FormatMetrics fm) {
         if (levelCounter == 1) {
             sb = new StringBuilder();
         }
     }
 
     @Override
-    public void endElement(@SuppressWarnings("hiding") RAbstractVector vector, int index, FormatMetrics fm) {
+    public void endElement(int index, FormatMetrics fm) {
         if (levelCounter == 1) {
             String s = sb.toString().trim();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
index 9acd7e244cc288467929467e5bbe82e73deb2c77..99957bfd751f46e4ab8d04a00db0119cc4f86153 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
@@ -23,6 +23,8 @@ import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter.Scien
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/printutils.c
 
@@ -52,13 +54,13 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            return formatComplexVector(vector, offs, len, 0, printCtx.parameters());
+            return formatComplexVector(iterator, access, offs, len, 0, printCtx.parameters());
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
             ComplexVectorMetrics cfm = (ComplexVectorMetrics) fm;
-            String v = encodeComplex(vector.getDataAt(i), cfm, '.', printCtx.parameters());
+            String v = encodeComplex(access.getComplex(iterator, i), cfm, '.', printCtx.parameters());
             out.print(v);
         }
 
@@ -74,69 +76,47 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
     }
 
     @TruffleBoundary
-    static ComplexVectorMetrics formatComplexVector(RAbstractComplexVector x, int offs, int n, int nsmall, PrintParameters pp) {
-        return formatComplexVector(x, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth());
+    static ComplexVectorMetrics formatComplexVector(RandomIterator iter, VectorAccess access, int offs, int n, int nsmall, PrintParameters pp) {
+        return formatComplexVector(iter, access, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth());
     }
 
     @TruffleBoundary
-    static ComplexVectorMetrics formatComplexVector(RAbstractComplexVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
-
-        int wr;
-        int dr;
-        int er;
-        int wi;
-        int di;
-        int ei;
+    static ComplexVectorMetrics formatComplexVector(RandomIterator iter, VectorAccess access, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
 
         /* format.info() or x[1..l] for both Re & Im */
-        int left;
-        int right;
-        int sleft;
         int rt;
         int mnl;
         int mxl;
         int mxsl;
         int mxns;
-        int wF;
-        int iwF;
         int irt;
         int imnl;
         int imxl;
         int imxsl;
         int imxns;
-        int neg;
-        boolean naflag;
-        boolean rnanflag;
-        boolean rposinf;
-        boolean rneginf;
-        boolean inanflag;
-        boolean iposinf;
-        RComplex tmp;
         boolean allReZero = true;
         boolean allImZero = true;
-
-        naflag = false;
-        rnanflag = false;
-        rposinf = false;
-        rneginf = false;
-        inanflag = false;
-        iposinf = false;
-        neg = 0;
-
+        boolean naflag = false;
+        boolean rnanflag = false;
+        boolean rposinf = false;
+        boolean rneginf = false;
+        boolean inanflag = false;
+        boolean iposinf = false;
+
+        int neg = 0;
         rt = mxl = mxsl = mxns = RRuntime.INT_MIN_VALUE;
         irt = imxl = imxsl = imxns = RRuntime.INT_MIN_VALUE;
         imnl = mnl = RRuntime.INT_MAX_VALUE;
 
         for (int i = 0; i < n; i++) {
             /* Now round */
-            RComplex xi = x.getDataAt(offs + i);
+            RComplex xi = access.getComplex(iter, offs + i);
             if (RRuntime.isNA(xi.getRealPart()) || RRuntime.isNA(xi.getImaginaryPart())) {
                 naflag = true;
             } else {
                 /* real part */
 
-                tmp = zprecr(xi, digits);
-
+                RComplex tmp = zprecr(xi, digits);
                 if (!RRuntime.isFinite(tmp.getRealPart())) {
                     if (RRuntime.isNAorNaN(tmp.getRealPart())) {
                         rnanflag = true;
@@ -151,12 +131,12 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
                     }
                     ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getRealPart(), digits);
 
-                    left = sd.kpower + 1;
+                    int left = sd.kpower + 1;
                     if (sd.roundingwidens) {
                         left--;
                     }
-                    sleft = sd.sgn + ((left <= 0) ? 1 : left); /* >= 1 */
-                    right = sd.nsig - left; /* #{digits} right of '.' ( > 0 often) */
+                    int sleft = sd.sgn + ((left <= 0) ? 1 : left); /* >= 1 */
+                    int right = sd.nsig - left; /* #{digits} right of '.' ( > 0 often) */
                     if (sd.sgn != 0) {
                         neg = 1; /* if any < 0, need extra space for sign */
                     }
@@ -194,12 +174,12 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
                     }
                     ScientificDouble sd = DoubleVectorPrinter.scientific(tmp.getImaginaryPart(), digits);
 
-                    left = sd.kpower + 1;
+                    int left = sd.kpower + 1;
                     if (sd.roundingwidens) {
                         left--;
                     }
-                    sleft = (left <= 0) ? 1 : left;
-                    right = sd.nsig - left;
+                    int sleft = (left <= 0) ? 1 : left;
+                    int right = sd.nsig - left;
 
                     if (right > irt) {
                         irt = right;
@@ -229,6 +209,11 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
         if (digits == 0) {
             rt = 0;
         }
+        int wr;
+        int dr;
+        int er;
+        int wi;
+        int wF;
         if (mxl != RRuntime.INT_MIN_VALUE) {
             if (mxl < 0) {
                 mxsl = 1 + neg;
@@ -253,6 +238,9 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
         if (digits == 0) {
             irt = 0;
         }
+        int di;
+        int ei;
+        int iwF;
         if (imxl != RRuntime.INT_MIN_VALUE) {
             if (imxl < 0) {
                 imxsl = 1;
@@ -400,8 +388,11 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
 
     @TruffleBoundary
     public static String encodeComplex(RComplex x, int digits, int sciPen, String naString) {
-        ComplexVectorMetrics cvm = formatComplexVector(x, 0, 1, 0, digits, sciPen, naString.length());
-        return encodeComplex(x, cvm, '.', digits, naString);
+        VectorAccess access = x.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(x)) {
+            ComplexVectorMetrics cvm = formatComplexVector(iter, access, 0, 1, 0, digits, sciPen, naString.length());
+            return encodeComplex(x, cvm, '.', digits, naString);
+        }
     }
 
     @TruffleBoundary
@@ -465,13 +456,19 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
     }
 
     public static String[] format(RAbstractComplexVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
-        ComplexVectorMetrics dfm = formatComplexVector(value, 0, value.getLength(), nsmall, pp);
-        ComplexVectorMetrics adjusted = new ComplexVectorMetrics(Math.max(trim ? 1 : dfm.wr, width), dfm.dr, dfm.er, Math.max(trim ? 1 : dfm.wi, width), dfm.di, dfm.ei);
-
-        String[] result = new String[value.getLength()];
-        for (int i = 0; i < value.getLength(); i++) {
-            result[i] = encodeComplex(value.getDataAt(i), adjusted, decimalMark, pp);
+        VectorAccess access = value.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(value)) {
+            int length = access.getLength(iter);
+            ComplexVectorMetrics dfm = formatComplexVector(iter, access, 0, length, nsmall, pp);
+            int wr = Math.max(trim ? 1 : dfm.wr, width);
+            int wi = Math.max(trim ? 1 : dfm.wi, width);
+            ComplexVectorMetrics adjusted = new ComplexVectorMetrics(wr, dfm.dr, dfm.er, wi, dfm.di, dfm.ei);
+
+            String[] result = new String[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = encodeComplex(access.getComplex(iter, i), adjusted, decimalMark, pp);
+            }
+            return result;
         }
-        return result;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
index 1c3df1c59f40dc33de4b909f935aa54be4febb28..afec29e85a7f87ca11f4ff92b22ba11dae5d90c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
@@ -15,8 +15,10 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/format.c
 
@@ -41,13 +43,13 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
 
         @Override
         protected DoubleVectorMetrics formatVector(int offs, int len) {
-            return formatDoubleVector(vector, offs, len, 0, printCtx.parameters());
+            return formatDoubleVector(iterator, access, offs, len, 0, printCtx.parameters());
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
             DoubleVectorMetrics dfm = (DoubleVectorMetrics) fm;
-            String v = encodeReal(vector.getDataAt(i), dfm.maxWidth, dfm.d, dfm.e, '.', printCtx.parameters());
+            String v = encodeReal(access.getDouble(iterator, i), dfm.maxWidth, dfm.d, dfm.e, '.', printCtx.parameters());
             out.print(v);
         }
 
@@ -68,12 +70,12 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
     }
 
     @TruffleBoundary
-    static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, PrintParameters pp) {
-        return formatDoubleVector(x, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth());
+    static DoubleVectorMetrics formatDoubleVector(RandomIterator iter, VectorAccess access, int offs, int n, int nsmall, PrintParameters pp) {
+        return formatDoubleVector(iter, access, offs, n, nsmall, pp.getDigits(), pp.getScipen(), pp.getNaWidth());
     }
 
     @TruffleBoundary
-    public static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
+    public static DoubleVectorMetrics formatDoubleVector(RandomIterator iter, VectorAccess access, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
         int left;
         int right;
         int sleft;
@@ -107,7 +109,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
         mnl = RRuntime.INT_MAX_VALUE;
 
         for (int i = 0; i < n; i++) {
-            double xi = x.getDataAt(i + offs);
+            double xi = access.getDouble(iter, offs + i);
             if (!RRuntime.isFinite(xi)) {
                 if (RRuntime.isNA(xi)) {
                     naflag = true;
@@ -368,8 +370,12 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
 
     @TruffleBoundary
     public static String encodeReal(double x, int digits, char cdec, int sciPen, String naString) {
-        DoubleVectorMetrics dm = formatDoubleVector(RDataFactory.createDoubleVectorFromScalar(x), 0, 1, 0, digits, sciPen, naString.length());
-        return encodeReal(x, dm.maxWidth, dm.d, dm.e, cdec, naString);
+        RDouble value = RDouble.valueOf(x);
+        VectorAccess access = value.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(value)) {
+            DoubleVectorMetrics dm = formatDoubleVector(iter, access, 0, 1, 0, digits, sciPen, naString.length());
+            return encodeReal(x, dm.maxWidth, dm.d, dm.e, cdec, naString);
+        }
     }
 
     @TruffleBoundary
@@ -563,13 +569,17 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
     }
 
     public static String[] format(RAbstractDoubleVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
-        DoubleVectorMetrics dfm = formatDoubleVector(value, 0, value.getLength(), nsmall, pp);
-        int w = Math.max(trim ? 1 : dfm.maxWidth, width);
-
-        String[] result = new String[value.getLength()];
-        for (int i = 0; i < value.getLength(); i++) {
-            result[i] = encodeReal(value.getDataAt(i), w, dfm.d, dfm.e, decimalMark, pp);
+        VectorAccess access = value.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(value)) {
+            int length = access.getLength(iter);
+            DoubleVectorMetrics dfm = formatDoubleVector(iter, access, 0, length, nsmall, pp);
+            int w = Math.max(trim ? 1 : dfm.maxWidth, width);
+
+            String[] result = new String[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = encodeReal(access.getDouble(iter, i), w, dfm.d, dfm.e, decimalMark, pp);
+            }
+            return result;
         }
-        return result;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
index f9d0ea7c4f89cb0cf9b1470a644d0615fee0eed6..6c7d6c4ae77dc7f4a932c91cec375c664c1083a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
@@ -17,6 +17,8 @@ import java.io.IOException;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/printutils.c, src/main/format.c
 
@@ -46,12 +48,12 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            return new FormatMetrics(formatIntVectorInternal(vector, offs, len, printCtx.parameters().getNaWidth()));
+            return new FormatMetrics(formatIntVectorInternal(iterator, access, offs, len, printCtx.parameters().getNaWidth()));
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String v = encodeInteger(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
+            String v = encodeInteger(access.getInt(iterator, i), fm.maxWidth, printCtx.parameters());
             out.print(v);
         }
 
@@ -66,7 +68,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
         }
     }
 
-    static int formatIntVectorInternal(RAbstractIntVector x, int offs, int n, int naWidth) {
+    static int formatIntVectorInternal(RandomIterator iter, VectorAccess access, int offs, int n, int naWidth) {
         int xmin = RRuntime.INT_MAX_VALUE;
         int xmax = RRuntime.INT_MIN_VALUE;
         boolean naflag = false;
@@ -74,7 +76,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
         int fieldwidth;
 
         for (int i = 0; i < n; i++) {
-            int xi = x.getDataAt(offs + i);
+            int xi = access.getInt(iter, offs + i);
             if (xi == RRuntime.INT_NA) {
                 naflag = true;
             } else {
@@ -164,18 +166,22 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
     }
 
     public static String[] format(RAbstractIntVector value, boolean trim, int width, PrintParameters pp) {
-        int w;
-        if (trim) {
-            w = 1;
-        } else {
-            w = formatIntVectorInternal(value, 0, value.getLength(), pp.getNaWidth());
-        }
-        w = Math.max(w, width);
+        VectorAccess access = value.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(value)) {
+            int w;
+            int length = access.getLength(iter);
+            if (trim) {
+                w = 1;
+            } else {
+                w = formatIntVectorInternal(iter, access, 0, length, pp.getNaWidth());
+            }
+            w = Math.max(w, width);
 
-        String[] result = new String[value.getLength()];
-        for (int i = 0; i < value.getLength(); i++) {
-            result[i] = encodeInteger(value.getDataAt(i), w, pp);
+            String[] result = new String[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = encodeInteger(access.getInt(iter, i), w, pp);
+            }
+            return result;
         }
-        return result;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index 7c84d1caf7a79c2145c6ad528bd222ee4e6ed597..65694c0578f9cc5c94f3c3b15bddb268ab7e8056 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -24,7 +24,6 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
-import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -36,6 +35,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/print.c
 
@@ -77,8 +78,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
             } else if (tmp instanceof RAbstractLogicalVector) {
                 RAbstractLogicalVector lv = (RAbstractLogicalVector) tmp;
                 if (lv.getLength() == 1) {
-                    int width = LogicalVectorPrinter.formatLogicalVectorInternal(lv, 0, 1, pp.getNaWidth());
-                    pbuf = LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), width, pp);
+                    pbuf = LogicalVectorPrinter.format(lv, false, 0, pp)[0];
                 } else {
                     pbuf = "Logical," + lv.getLength();
                 }
@@ -89,8 +89,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                     pbuf = "factor," + iv.getLength();
                 } else {
                     if (iv.getLength() == 1) {
-                        int width = IntegerVectorPrinter.formatIntVectorInternal(iv, 0, 1, pp.getNaWidth());
-                        pbuf = IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), width, pp);
+                        pbuf = IntegerVectorPrinter.format(iv, false, 0, pp)[0];
                     } else {
                         pbuf = "Integer," + iv.getLength();
                     }
@@ -98,31 +97,26 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
             } else if (tmp instanceof RAbstractDoubleVector) {
                 RAbstractDoubleVector dv = (RAbstractDoubleVector) tmp;
                 if (dv.getLength() == 1) {
-                    DoubleVectorMetrics fm = DoubleVectorPrinter.formatDoubleVector(dv, 0, 1, 0, pp);
-                    pbuf = DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp);
+                    pbuf = DoubleVectorPrinter.format(dv, false, 0, 0, '.', pp)[0];
                 } else {
                     pbuf = "Numeric," + dv.getLength();
                 }
             } else if (tmp instanceof RAbstractComplexVector) {
                 RAbstractComplexVector cv = (RAbstractComplexVector) tmp;
                 if (cv.getLength() == 1) {
-                    RComplex x = cv.getDataAt(0);
-                    if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) {
-                        /* formatReal(NA) --> w=R_print.na_width, d=0, e=0 */
-                        pbuf = DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp);
-                    } else {
-                        ComplexVectorMetrics cvm = ComplexVectorPrinter.formatComplexVector(x, 0, 1, 0, pp);
-                        pbuf = ComplexVectorPrinter.encodeComplex(x, cvm, '.', pp);
-                    }
+                    pbuf = ComplexVectorPrinter.format(cv, false, 0, 0, '.', pp)[0];
                 } else {
                     pbuf = "Complex," + cv.getLength();
                 }
             } else if (tmp instanceof RAbstractStringVector) {
                 RAbstractStringVector sv = (RAbstractStringVector) tmp;
                 if (sv.getLength() == 1) {
-                    String ctmp = RRuntime.escapeString(sv.getDataAt(0), true, true);
-                    int len = ctmp.length();
-                    if (len < 100) {
+                    String ctmp;
+                    VectorAccess access = sv.slowPathAccess();
+                    try (RandomIterator iter = access.randomAccess(sv)) {
+                        ctmp = RRuntime.escapeString(access.getString(iter, 0), true, true);
+                    }
+                    if (ctmp.length() < 100) {
                         pbuf = ctmp;
                     } else {
                         pbuf = Utils.trimSize(101, ctmp) + "\" [truncated]";
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
index 3421a15d5b01f989d577a8e5b274bea67a117002..7bb3d8274d49d4b4eebab8c3471a899445392726 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
@@ -15,6 +15,8 @@ import java.io.IOException;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/printutils.c, src/main/format.c
 
@@ -44,12 +46,12 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            return new FormatMetrics(formatLogicalVectorInternal(vector, offs, len, printCtx.parameters().getNaWidth()));
+            return new FormatMetrics(formatLogicalVectorInternal(iterator, access, offs, len, printCtx.parameters().getNaWidth()));
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            out.print(encodeLogical(vector.getDataAt(i), fm.maxWidth, printCtx.parameters()));
+            out.print(encodeLogical(access.getLogical(iterator, i), fm.maxWidth, printCtx.parameters()));
         }
 
         @Override
@@ -63,10 +65,10 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
         }
     }
 
-    static int formatLogicalVectorInternal(RAbstractLogicalVector x, int offs, int n, int naWidth) {
+    static int formatLogicalVectorInternal(RandomIterator iter, VectorAccess access, int offs, int n, int naWidth) {
         int fieldwidth = 1;
         for (int i = 0; i < n; i++) {
-            byte xi = x.getDataAt(offs + i);
+            byte xi = access.getLogical(iter, offs + i);
             if (xi == RRuntime.LOGICAL_NA) {
                 if (fieldwidth < naWidth) {
                     fieldwidth = naWidth;
@@ -105,18 +107,22 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
     }
 
     public static String[] format(RAbstractLogicalVector value, boolean trim, int width, PrintParameters pp) {
-        int w;
-        if (trim) {
-            w = 1;
-        } else {
-            w = formatLogicalVectorInternal(value, 0, value.getLength(), pp.getNaWidth());
-        }
-        w = Math.max(w, width);
+        VectorAccess access = value.slowPathAccess();
+        try (RandomIterator iter = access.randomAccess(value)) {
+            int length = access.getLength(iter);
+            int w;
+            if (trim) {
+                w = 1;
+            } else {
+                w = formatLogicalVectorInternal(iter, access, 0, length, pp.getNaWidth());
+            }
+            w = Math.max(w, width);
 
-        String[] result = new String[value.getLength()];
-        for (int i = 0; i < value.getLength(); i++) {
-            result[i] = encodeLogical(value.getDataAt(i), w, pp);
+            String[] result = new String[value.getLength()];
+            for (int i = 0; i < length; i++) {
+                result[i] = encodeLogical(access.getLogical(iter, i), w, pp);
+            }
+            return result;
         }
-        return result;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyPrintWriter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyPrintWriter.java
index 675bb97080f397e81113ed17aa37d1a63bad2182..138cbe4e58af0de7b3ab12f7b71c657e752da9e6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyPrintWriter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyPrintWriter.java
@@ -26,7 +26,6 @@ import java.io.PrintWriter;
 import java.io.Writer;
 
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public class PrettyPrintWriter extends PrintWriter implements PrettyWriter {
 
@@ -81,16 +80,16 @@ public class PrettyPrintWriter extends PrintWriter implements PrettyWriter {
     }
 
     @Override
-    public void beginElement(RAbstractVector vector, int index, FormatMetrics fm) {
+    public void beginElement(int index, FormatMetrics fm) {
         if (out instanceof PrettyWriter) {
-            ((PrettyWriter) out).beginElement(vector, index, fm);
+            ((PrettyWriter) out).beginElement(index, fm);
         }
     }
 
     @Override
-    public void endElement(RAbstractVector vector, int index, FormatMetrics fm) {
+    public void endElement(int index, FormatMetrics fm) {
         if (out instanceof PrettyWriter) {
-            ((PrettyWriter) out).endElement(vector, index, fm);
+            ((PrettyWriter) out).endElement(index, fm);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyWriter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyWriter.java
index 9813e5cc9f439bee7ebc325a254a6a202dc9568e..b54c046686781bb656aa878817e2d9ed1efb2ff5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyWriter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrettyWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public interface PrettyWriter {
 
@@ -39,9 +38,9 @@ public interface PrettyWriter {
 
     void endAttributes(RAttributeStorage value);
 
-    void beginElement(RAbstractVector vector, int index, FormatMetrics fm);
+    void beginElement(int index, FormatMetrics fm);
 
-    void endElement(RAbstractVector vector, int index, FormatMetrics fm);
+    void endElement(int index, FormatMetrics fm);
 
     Object getPrintReport();
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
index bf648a7aa9f0280a5bbfa9ab0e4b0981ed74ea3d..f3ffdebdd96170f6dcf74d4e6507b02f4e850a41 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RawVectorPrinter.java
@@ -60,7 +60,7 @@ final class RawVectorPrinter extends VectorPrinter<RAbstractRawVector> {
         @Override
         @TruffleBoundary
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String rs = RRuntime.rawToHexString(vector.getRawDataAt(i));
+            String rs = RRuntime.rawToHexString(access.getRaw(iterator, i));
             if (fm.maxWidth > 2) {
                 StringBuilder str = new StringBuilder(fm.maxWidth);
                 for (int j = 2; j < fm.maxWidth; j++) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrettyWriter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrettyWriter.java
index de109409424251285af7b61c24615bf440702913..0e188fffc786d79c7f77ef0240e3799293aeaa02 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrettyWriter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringPrettyWriter.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base.printer;
 import java.io.StringWriter;
 
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public class StringPrettyWriter extends StringWriter implements PrettyWriter {
 
@@ -54,11 +53,11 @@ public class StringPrettyWriter extends StringWriter implements PrettyWriter {
     }
 
     @Override
-    public void beginElement(RAbstractVector vector, int index, FormatMetrics fm) {
+    public void beginElement(int index, FormatMetrics fm) {
     }
 
     @Override
-    public void endElement(RAbstractVector vector, int index, FormatMetrics fm) {
+    public void endElement(int index, FormatMetrics fm) {
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
index 5ba2ea9ebc1e0f52b2601b313cda108089ada5a4..13937fca383ca7404f733dde9edde436038b5e35 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
@@ -18,6 +18,8 @@ import java.util.Arrays;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/format.c
 
@@ -42,19 +44,19 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> {
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            int w = formatString(vector, offs, len, quote, printCtx.parameters());
+            int w = formatString(iterator, access, offs, len, quote, printCtx.parameters());
             return new FormatMetrics(w);
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String s = vector.getDataAt(i);
+            String s = access.getString(iterator, i);
             StringVectorPrinter.printString(s, fm.maxWidth, printCtx);
         }
 
         @Override
         protected void printCell(int i, FormatMetrics fm) throws IOException {
-            String s = vector.getDataAt(i);
+            String s = access.getString(iterator, i);
             String outS = StringVectorPrinter.encode(s, fm.maxWidth, printCtx.parameters());
             int g = printCtx.parameters().getGap();
             String fmt = "%" + asBlankArg(g) + "s%s";
@@ -95,7 +97,7 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> {
         }
     }
 
-    static int formatString(RAbstractStringVector x, int offs, int n, boolean quote, PrintParameters pp) {
+    static int formatString(RandomIterator iter, VectorAccess access, int offs, int n, boolean quote, PrintParameters pp) {
         int xmax = 0;
         int l;
 
@@ -103,7 +105,7 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> {
         int fieldwidth;
 
         for (int i = 0; i < n; i++) {
-            String s = x.getDataAt(offs + i);
+            String s = access.getString(iter, offs + i);
             String xi = RRuntime.escapeString(s, false, quote);
 
             if (xi == RRuntime.STRING_NA) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
index e2a12e3ae18c0977f6db8c47300dac10950c6080..4a97ef3b3c4ec5e5cbd0ce13ce951147906e4848 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
@@ -24,6 +24,8 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.RandomIterator;
 
 //Transcribed from GnuR, src/main/print.c, src/main/printarray.c, src/main/printvector.c
 
@@ -35,7 +37,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
     }
 
     public void printVector(T vector, int indx, PrintContext printCtx) throws IOException {
-        createJob(vector, indx, printCtx).print();
+        createJob(vector, indx, printCtx).print(vector);
     }
 
     protected abstract VectorPrintJob createJob(T vector, int indx, PrintContext printCtx);
@@ -53,7 +55,8 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
 
     protected abstract class VectorPrintJob {
 
-        protected final T vector;
+        protected VectorAccess access;
+        protected RandomIterator iterator;
         protected final int n;
         protected final int nPr;
         protected final int indx;
@@ -69,13 +72,13 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
         protected final boolean supressIndexLabels;
 
         protected VectorPrintJob(T vector, int indx, PrintContext printCtx) {
-            this.vector = vector;
             this.indx = indx;
             this.quote = printCtx.parameters().getQuote();
 
             MatrixDimNames mdn = null;
 
             Object dimAttr = getDims(vector);
+            int length = vector.getLength();
             if (dimAttr instanceof RAbstractIntVector) {
                 dims = (RAbstractIntVector) dimAttr;
                 if (dims.getLength() == 1) {
@@ -89,12 +92,12 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                             title = null;
                         }
 
-                        jobMode = vector.getLength() == 0 ? JobMode.namedEmpty : JobMode.named;
+                        jobMode = length == 0 ? JobMode.namedEmpty : JobMode.named;
                         names = Utils.castTo(RRuntime.convertScalarVectors(t.getDataAt(0)));
                     } else {
                         title = null;
                         names = null;
-                        jobMode = vector.getLength() == 0 ? JobMode.empty : JobMode.nonEmpty;
+                        jobMode = length == 0 ? JobMode.empty : JobMode.nonEmpty;
                     }
                 } else if (dims.getLength() == 2) {
                     mdn = new MatrixDimNames(vector);
@@ -111,14 +114,14 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                 dims = null;
                 Object namesAttr = Utils.castTo(getNames(vector));
                 if (namesAttr != null) {
-                    if (vector.getLength() > 0) {
+                    if (length > 0) {
                         names = Utils.castTo(RRuntime.convertScalarVectors(namesAttr));
                         jobMode = JobMode.named;
                     } else {
                         names = null;
                         jobMode = JobMode.namedEmpty;
                     }
-                } else if (vector.getLength() > 0) {
+                } else if (length > 0) {
                     jobMode = JobMode.nonEmpty;
                     names = null;
                 } else {
@@ -134,32 +137,36 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                 this.printCtx.parameters().setRight(true);
             }
             this.out = this.printCtx.output();
-            this.n = vector.getLength();
+            this.n = length;
             int max = printCtx.parameters().getMax();
             this.nPr = (n <= max + 1) ? n : max;
             this.labwidth = indexWidth(n) + 2;
             this.matrixDimNames = mdn;
         }
 
-        public void print() throws IOException {
-            switch (jobMode) {
-                case empty:
-                    printEmptyVector();
-                    break;
-                case nonEmpty:
-                    printNonEmptyVector();
-                    break;
-                case named:
-                    printNamedVector();
-                    break;
-                case namedEmpty:
-                    printNamedEmptyVector();
-                    break;
-                case matrix:
-                    printMatrix();
-                    break;
-                case array:
-                    printArray();
+        public final void print(T vector) throws IOException {
+            access = vector.access();
+            try (RandomIterator iter = access.randomAccess(vector)) {
+                this.iterator = iter;
+                switch (jobMode) {
+                    case empty:
+                        printEmptyVector();
+                        break;
+                    case nonEmpty:
+                        printNonEmptyVector();
+                        break;
+                    case named:
+                        printNamedVector();
+                        break;
+                    case namedEmpty:
+                        printNamedEmptyVector();
+                        break;
+                    case matrix:
+                        printMatrix();
+                        break;
+                    case array:
+                        printArray();
+                }
             }
         }
 
@@ -209,7 +216,10 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
 
             PrintParameters pp = printCtx.parameters();
 
-            wn = StringVectorPrinter.formatString(names, 0, n, false, pp);
+            VectorAccess namesAccess = names.slowPathAccess();
+            try (RandomIterator namesIter = namesAccess.randomAccess(names)) {
+                wn = StringVectorPrinter.formatString(namesIter, namesAccess, 0, n, false, pp);
+            }
             if (fm.maxWidth < wn) {
                 fm.maxWidth = wn;
             }
@@ -302,7 +312,10 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
             int lbloff = 0;
 
             if (rl != null) {
-                rlabw = StringVectorPrinter.formatString(rl, 0, r, false, pp);
+                VectorAccess rlAccess = rl.slowPathAccess();
+                try (RandomIterator rlIter = rlAccess.randomAccess(rl)) {
+                    rlabw = StringVectorPrinter.formatString(rlIter, rlAccess, 0, r, false, pp);
+                }
             } else {
                 rlabw = indexWidth(r + 1) + 3;
             }
@@ -609,9 +622,9 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
         protected abstract void printElement(int i, FormatMetrics fm) throws IOException;
 
         private void printElementAndNotify(int i, FormatMetrics fm) throws IOException {
-            out.beginElement(vector, i, fm);
+            out.beginElement(i, fm);
             printElement(i, fm);
-            out.endElement(vector, i, fm);
+            out.endElement(i, fm);
         }
 
         /**
@@ -625,9 +638,9 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
         protected abstract void printCell(int i, FormatMetrics fm) throws IOException;
 
         private void printCellAndNotify(int i, FormatMetrics fm) throws IOException {
-            out.beginElement(vector, i, fm);
+            out.beginElement(i, fm);
             printCell(i, fm);
-            out.endElement(vector, i, fm);
+            out.endElement(i, fm);
         }
 
         protected int matrixIndividualCellColumnWidthCorrection() {
@@ -713,7 +726,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
     }
 
     @TruffleBoundary
-    private static Object getNames(RAbstractVector vector) {
-        return vector.getAttr(RRuntime.NAMES_ATTR_KEY);
+    private static Object getNames(RAbstractVector x) {
+        return x.getAttr(RRuntime.NAMES_ATTR_KEY);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java
index 6a67f4c389310fd510d10f658549f03a3d35d072..20f59b813a625a99f5a3308fb9dd0a8feb549e2b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignListWrapper.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.nodes.FastPathVectorAccess.FastPathFromListAccess;
 import com.oracle.truffle.r.runtime.data.nodes.SlowPathVectorAccess.SlowPathFromListAccess;
 import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
 
 public final class RForeignListWrapper extends RForeignWrapper implements RAbstractListVector {
 
@@ -58,7 +59,7 @@ public final class RForeignListWrapper extends RForeignWrapper implements RAbstr
     @TruffleBoundary
     public Object getDataAt(int index) {
         try {
-            return ForeignAccess.sendRead(READ, delegate, index);
+            return FOREIGN_TO_R.execute(ForeignAccess.sendRead(READ, delegate, index));
         } catch (UnsupportedMessageException | UnknownIdentifierException e) {
             throw RInternalError.shouldNotReachHere(e);
         }
@@ -72,6 +73,7 @@ public final class RForeignListWrapper extends RForeignWrapper implements RAbstr
 
         @Child private Node getSize = Message.GET_SIZE.createNode();
         @Child private Node read = Message.READ.createNode();
+        @Child private Foreign2R foreign2r = Foreign2R.create();
 
         @Override
         public RType getType() {
@@ -90,7 +92,7 @@ public final class RForeignListWrapper extends RForeignWrapper implements RAbstr
         @Override
         protected Object getListElement(Object internalStore, int index) {
             try {
-                return ForeignAccess.sendRead(read, (TruffleObject) internalStore, index);
+                return foreign2r.execute(ForeignAccess.sendRead(read, (TruffleObject) internalStore, index));
             } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
@@ -102,7 +104,10 @@ public final class RForeignListWrapper extends RForeignWrapper implements RAbstr
         return new FastPathAccess(this);
     }
 
+    private static final Foreign2R FOREIGN_TO_R = Foreign2R.create();
+
     private static final SlowPathFromListAccess SLOW_PATH_ACCESS = new SlowPathFromListAccess() {
+
         @Override
         public RType getType() {
             return RType.List;
@@ -122,7 +127,7 @@ public final class RForeignListWrapper extends RForeignWrapper implements RAbstr
         protected Object getListElement(Object store, int index) {
             RForeignListWrapper vector = (RForeignListWrapper) store;
             try {
-                return ForeignAccess.sendRead(READ, vector.delegate, index);
+                return FOREIGN_TO_R.execute(ForeignAccess.sendRead(READ, vector.delegate, index));
             } catch (UnsupportedMessageException | UnknownIdentifierException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java
index 79350c7cb3ec54287815eff5219e15f80f6004f4..36fece25f3205667f6fae6080373c2bb3e06e2ce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java
@@ -46,7 +46,7 @@ public abstract class RForeignWrapper implements RAbstractVector {
 
     @Override
     @TruffleBoundary
-    public final int getLength() {
+    public int getLength() {
         try {
             return (int) ForeignAccess.sendGetSize(GET_SIZE, delegate);
         } catch (UnsupportedMessageException e) {
@@ -100,7 +100,7 @@ public abstract class RForeignWrapper implements RAbstractVector {
     }
 
     @Override
-    public final RStringVector getNames() {
+    public RStringVector getNames() {
         return null;
     }
 
@@ -183,7 +183,7 @@ public abstract class RForeignWrapper implements RAbstractVector {
     }
 
     @Override
-    public final Object getInternalStore() {
+    public Object getInternalStore() {
         return delegate;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/TruffleObjectConverter.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/TruffleObjectConverter.java
index 798006a13b57040f459279e096fa87dbc0b99efd..e939f44b7a402218b413034d9093cf367251f961 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/TruffleObjectConverter.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/TruffleObjectConverter.java
@@ -26,30 +26,18 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.UnknownIdentifierException;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RAttributeStorage;
-import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RForeignBooleanWrapper;
+import com.oracle.truffle.r.runtime.data.RForeignDoubleWrapper;
+import com.oracle.truffle.r.runtime.data.RForeignIntWrapper;
+import com.oracle.truffle.r.runtime.data.RForeignListWrapper;
+import com.oracle.truffle.r.runtime.data.RForeignNamedListWrapper;
+import com.oracle.truffle.r.runtime.data.RForeignStringWrapper;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.RVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
 
 public final class TruffleObjectConverter {
 
@@ -59,93 +47,13 @@ public final class TruffleObjectConverter {
     private Node isBoxedNode = com.oracle.truffle.api.interop.Message.IS_BOXED.createNode();
     private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode();
     private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode();
-    private Foreign2R foreign2R = Foreign2R.create();
-
-    public TruffleObjectConverter() {
-    }
 
     public Node[] getSubNodes() {
-        return new Node[]{
-                        hasSizeNode, getSizeNode, readNode, isBoxedNode, unboxNode, keysNode, foreign2R
-        };
+        return new Node[]{hasSizeNode, getSizeNode, readNode, isBoxedNode, unboxNode, keysNode};
     }
 
     @TruffleBoundary
     public Object convert(TruffleObject obj) {
-        class RStringWrapper extends TruffleObjectWrapper implements RAbstractStringVector {
-            final TruffleObject object;
-
-            RStringWrapper(int length, TruffleObject object) {
-                super(length);
-                this.object = object;
-            }
-
-            @Override
-            @TruffleBoundary
-            public Object getDataAtAsObject(int index) {
-                return getDataAt(index);
-            }
-
-            @Override
-            @TruffleBoundary
-            public String getDataAt(int index) {
-                Object value;
-                try {
-                    value = ForeignAccess.sendRead(readNode, object, index);
-                    return String.valueOf(foreign2R.execute(value));
-                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                    throw RInternalError.shouldNotReachHere(e);
-                }
-            }
-
-            @Override
-            @TruffleBoundary
-            public RStringVector materialize() {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-        class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector {
-
-            private final RStringVector names;
-
-            RListWrapper(int length, RStringVector names) {
-                super(length);
-                this.names = names;
-                if (names != null) {
-                    DynamicObject attrs = RAttributesLayout.createNames(names);
-                    initAttributes(attrs);
-                }
-            }
-
-            @Override
-            @TruffleBoundary
-            public Object getDataAtAsObject(int index) {
-                return getDataAt(index);
-            }
-
-            @Override
-            @TruffleBoundary
-            public Object getDataAt(int index) {
-                try {
-                    Object value = ForeignAccess.sendRead(readNode, obj, names != null ? names.getDataAt(index) : index);
-                    return foreign2R.execute(value);
-                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                    throw RInternalError.shouldNotReachHere(e);
-                }
-            }
-
-            @Override
-            @TruffleBoundary
-            public RStringVector getNames() {
-                return names;
-            }
-
-            @Override
-            @TruffleBoundary
-            public RList materialize() {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
         try {
             if (ForeignAccess.sendHasSize(hasSizeNode, obj)) {
                 int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, obj);
@@ -161,102 +69,15 @@ public final class TruffleObjectConverter {
                 }
                 switch (typeCheck.getType()) {
                     case BOOLEAN:
-                        class RLogicalWrapper extends TruffleObjectWrapper implements RAbstractLogicalVector {
-
-                            RLogicalWrapper(int length) {
-                                super(length);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public byte getDataAt(int index) {
-                                try {
-                                    Object value = ForeignAccess.sendRead(readNode, obj, index);
-                                    return (byte) foreign2R.execute(value);
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
-                                }
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public RLogicalVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
-                            }
-                        }
-                        return new RLogicalWrapper(size);
+                        return new RForeignBooleanWrapper(obj);
                     case INTEGER:
-                        class RIntWrapper extends TruffleObjectWrapper implements RAbstractIntVector {
-
-                            RIntWrapper(int length) {
-                                super(length);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public int getDataAt(int index) {
-                                try {
-                                    Object value = ForeignAccess.sendRead(readNode, obj, index);
-                                    return ((Number) foreign2R.execute(value)).intValue();
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
-                                }
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public RIntVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
-                            }
-                        }
-                        return new RIntWrapper(size);
+                        return new RForeignIntWrapper(obj);
                     case DOUBLE:
-                        class RDoubleWrapper extends TruffleObjectWrapper implements RAbstractDoubleVector {
-
-                            RDoubleWrapper(int length) {
-                                super(length);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public Object getDataAtAsObject(int index) {
-                                return getDataAt(index);
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public double getDataAt(int index) {
-                                try {
-                                    Object value = ForeignAccess.sendRead(readNode, obj, index);
-                                    return ((Number) foreign2R.execute(value)).doubleValue();
-                                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
-                                    throw RInternalError.shouldNotReachHere(e);
-                                }
-                            }
-
-                            @Override
-                            @TruffleBoundary
-                            public RDoubleVector materialize() {
-                                throw RInternalError.shouldNotReachHere();
-                            }
-                        }
-                        return new RDoubleWrapper(size);
+                        return new RForeignDoubleWrapper(obj);
                     case STRING:
-                        return new RStringWrapper(size, obj);
+                        return new RForeignStringWrapper(obj);
                     case NONE:
-                        return new RListWrapper(size, null);
+                        return new RForeignListWrapper(obj);
                     default:
                         throw RInternalError.shouldNotReachHere();
                 }
@@ -264,7 +85,7 @@ public final class TruffleObjectConverter {
             TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
             if (keys != null) {
                 int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
-                RAbstractStringVector abstractNames = new RStringWrapper(size, keys);
+                RAbstractStringVector abstractNames = new RForeignStringWrapper(keys);
                 String[] namesData = new String[size];
                 boolean namesComplete = true;
                 for (int i = 0; i < size; i++) {
@@ -273,150 +94,11 @@ public final class TruffleObjectConverter {
                 }
                 RStringVector names = RDataFactory.createStringVector(namesData, namesComplete);
 
-                return new RListWrapper(size, names);
+                return new RForeignNamedListWrapper(obj, names);
             }
         } catch (InteropException e) {
             // nothing to do
         }
         return obj;
     }
-
-    private abstract static class TruffleObjectWrapper extends RAttributeStorage implements RAbstractVector {
-
-        private final int length;
-
-        TruffleObjectWrapper(int length) {
-            this.length = length;
-        }
-
-        @Override
-        public Object getInternalStore() {
-            return this;
-        }
-
-        @Override
-        public RAbstractVector copy() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RVector<?> copyResized(int size, boolean fillNA) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RAbstractVector copyWithNewDimensions(int[] newDimensions) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RAbstractVector copyDropAttributes() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public boolean isMatrix() {
-            return false;
-        }
-
-        @Override
-        public boolean isArray() {
-            return false;
-        }
-
-        @Override
-        public void setComplete(boolean complete) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public boolean isComplete() {
-            return false;
-        }
-
-        @Override
-        public int getLength() {
-            return length;
-        }
-
-        @Override
-        public RAbstractContainer resize(int size) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public boolean hasDimensions() {
-            return false;
-        }
-
-        @Override
-        public int[] getDimensions() {
-            return null;
-        }
-
-        @Override
-        public void setDimensions(int[] newDimensions) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RTypedValue getNonShared() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RStringVector getNames() {
-            return null;
-        }
-
-        @Override
-        public final void setNames(RStringVector newNames) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public RList getDimNames() {
-            return null;
-        }
-
-        @Override
-        public void setDimNames(RList newDimNames) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public Object getRowNames() {
-            return null;
-        }
-
-        @Override
-        public void setRowNames(RAbstractVector rowNames) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public ForeignAccess getForeignAccess() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public VectorAccess access() {
-            throw RInternalError.unimplemented("access() for " + getClass().getSimpleName());
-        }
-
-        @Override
-        public VectorAccess slowPathAccess() {
-            throw RInternalError.unimplemented("slowPathAccess() for " + getClass().getSimpleName());
-        }
-    }
 }