diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index e883fc44c570cd9ca10913bff2b7624ae5095602..005d49ee57fc65f2b4570d33060f89c9bb0bca5f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -28,9 +28,8 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.BaseGammaFunctionsFactory.DpsiFnCalcNodeGen;
 import com.oracle.truffle.r.runtime.RError;
@@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.nmath.GammaFunctions;
 import com.oracle.truffle.r.runtime.nmath.RMath;
-import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class BaseGammaFunctions {
@@ -110,7 +108,7 @@ public class BaseGammaFunctions {
         private double dpsiFnCalc(double x, int n, int kode, double ans) {
             if (dpsiFnCalc == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dpsiFnCalc = insert(DpsiFnCalcNodeGen.create(null, null, null, null));
+                dpsiFnCalc = insert(DpsiFnCalcNodeGen.create());
             }
             return dpsiFnCalc.executeDouble(x, n, kode, ans);
         }
@@ -156,8 +154,7 @@ public class BaseGammaFunctions {
         }
     }
 
-    @NodeChildren({@NodeChild(value = "x"), @NodeChild(value = "n"), @NodeChild(value = "kode"), @NodeChild(value = "ans")})
-    protected abstract static class DpsiFnCalc extends RNode {
+    protected abstract static class DpsiFnCalc extends Node {
 
         // the following is transcribed from polygamma.c
 
@@ -179,7 +176,7 @@ public class BaseGammaFunctions {
         private double dpsiFnCalc(double x, int n, int kode, double ans) {
             if (dpsiFnCalc == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dpsiFnCalc = insert(DpsiFnCalcNodeGen.create(null, null, null, null));
+                dpsiFnCalc = insert(DpsiFnCalcNodeGen.create());
             }
             return dpsiFnCalc.executeDouble(x, n, kode, ans);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
index 4fd7a02227ede680e2b79f60338690e831e27a27..f51a45e0d95e883c1f8039ad0b950dd30f8a2e07 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -88,7 +88,7 @@ public abstract class Mapply extends RBuiltinNode {
             this.vectorElementName = "*" + AnonymousFrameVariable.create(vectorElementName);
             this.lengthNode = insert(LengthNodeGen.create());
             this.indexedLoadNode = insert(SubscriptNodeGen.create());
-            this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, null, Mode.REGULAR));
+            this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, Mode.REGULAR, null));
             this.argName = argName;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 0cd7b5397c8821cdc1278d237bf9074be477661f..501753254b73bcfac9933452900ba9ae7c2b3929 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -172,7 +171,7 @@ class SpecialsUtils {
     }
 
     @NodeInfo(cost = NodeCost.NONE)
-    @NodeChildren({@NodeChild(value = "delegate", type = RNode.class)})
+    @NodeChild(value = "delegate", type = RNode.class)
     @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     public abstract static class ConvertIndex extends RNode {
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 176b95d29c7d08835e24a8acc0ab34b0cf7c7d8a..144f70966bb6ff034fb6de41078cce871018e1e5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -66,7 +65,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 /**
  * Subscript code for vectors minus list is the same as subset code, this class allows sharing it.
  */
-@NodeChildren({@NodeChild(value = "vector", type = ProfiledValue.class), @NodeChild(value = "index", type = ConvertIndex.class)})
+@NodeChild(value = "vector", type = ProfiledValue.class)
+@NodeChild(value = "index", type = ConvertIndex.class)
 abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 
     protected SubscriptSpecialBase(boolean inReplacement) {
@@ -104,7 +104,9 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 /**
  * Subscript code for matrices minus list is the same as subset code, this class allows sharing it.
  */
-@NodeChildren({@NodeChild(value = "vector", type = ProfiledValue.class), @NodeChild(value = "index1", type = ConvertIndex.class), @NodeChild(value = "index2", type = ConvertIndex.class)})
+@NodeChild(value = "vector", type = ProfiledValue.class)
+@NodeChild(value = "index1", type = ConvertIndex.class)
+@NodeChild(value = "index2", type = ConvertIndex.class)
 abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
 
     protected SubscriptSpecial2Base(boolean inReplacement) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index 432d1c31a52325e64196631bab028e1ef0c15ca2..cfc2f94db133139d1c2ff70524b496ab21a1b2ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -32,7 +32,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -60,7 +59,9 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@NodeChildren({@NodeChild(value = "vector", type = ProfiledValue.class), @NodeChild(value = "index", type = ConvertIndex.class), @NodeChild(value = "value", type = RNode.class)})
+@NodeChild(value = "vector", type = ProfiledValue.class)
+@NodeChild(value = "index", type = ConvertIndex.class)
+@NodeChild(value = "value", type = RNode.class)
 abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
 
     protected UpdateSubscriptSpecial(boolean inReplacement) {
@@ -108,8 +109,10 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
     }
 }
 
-@NodeChildren({@NodeChild(value = "vector", type = ProfiledValue.class), @NodeChild(value = "index1", type = ConvertIndex.class), @NodeChild(value = "index2", type = ConvertIndex.class),
-                @NodeChild(value = "value", type = RNode.class)})
+@NodeChild(value = "vector", type = ProfiledValue.class)
+@NodeChild(value = "index1", type = ConvertIndex.class)
+@NodeChild(value = "index2", type = ConvertIndex.class)
+@NodeChild(value = "value", type = RNode.class)
 abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
 
     protected UpdateSubscriptSpecial2(boolean inReplacement) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index 62d0f967d398196c10f3b9af42dccd8289344232..24f773ecefd8797ac57073bf5f97e2ad202c743b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -24,8 +24,6 @@ package com.oracle.truffle.r.nodes.access;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeField;
-import com.oracle.truffle.api.dsl.NodeFields;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
@@ -38,7 +36,6 @@ import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @NodeChild(value = "rhs", type = RNode.class)
-@NodeFields({@NodeField(name = "name", type = Object.class)})
 /**
  * Common code/state for all the variants of {@code WriteVariableNode}. At this level, we just have
  * a {@code name} for the variable and expression {@code rhs} to be assigned to.
@@ -47,6 +44,10 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 abstract class BaseWriteVariableNode extends WriteVariableNode {
 
+    protected BaseWriteVariableNode(Object name) {
+        super(name);
+    }
+
     private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile isCurrentProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile isShareableProfile = ConditionProfile.createBinaryProfile();
@@ -136,7 +137,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
         return isKind(frameSlot, FrameSlotKind.Double);
     }
 
-    private boolean isKind(FrameSlot frameSlot, FrameSlotKind kind) {
+    protected boolean isKind(FrameSlot frameSlot, FrameSlotKind kind) {
         if (frameSlot.getKind() == kind) {
             return true;
         } else {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
index 7e26af3cfc74ef2b47e2425709fd00e184a72282..19807b04e4b2cec07b620c46439638b6bf5f5942 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.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
@@ -22,118 +22,73 @@
  */
 package com.oracle.truffle.r.nodes.access;
 
-import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.findOrAddFrameSlot;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.NodeField;
-import com.oracle.truffle.api.dsl.NodeFields;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.NodeCost;
-import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNodeFactory.ResolvedWriteLocalFrameVariableNodeGen;
-import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNodeFactory.UnresolvedWriteLocalFrameVariableNodeGen;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 /**
  * {@link WriteLocalFrameVariableNode} captures a write to the "local", i.e., current, frame. There
  * are several clients capturing different "kinds" of writes to the frame, e.g. saving an argument,
- * a source-level write, a a write helper for another source node (e.g. {@code ForNode}.
- *
- * The state starts out a "unresolved" and transforms to "resolved".
+ * a source-level write, a a write helper for another source node (e.g. {@code ForNode}).
  */
+@ImportStatic(FrameSlotKind.class)
 public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode {
 
-    public static WriteLocalFrameVariableNode create(String name, RNode rhs, Mode mode) {
-        return UnresolvedWriteLocalFrameVariableNodeGen.create(rhs, name, mode);
+    public static WriteLocalFrameVariableNode create(Object name, Mode mode, RNode rhs) {
+        return WriteLocalFrameVariableNodeGen.create(name, mode, rhs);
     }
 
     public static WriteLocalFrameVariableNode createForRefCount(Object name) {
-        return UnresolvedWriteLocalFrameVariableNodeGen.create(null, name, Mode.INVISIBLE);
+        return WriteLocalFrameVariableNodeGen.create(name, Mode.INVISIBLE, null);
     }
 
-    @NodeField(name = "mode", type = Mode.class)
-    @NodeInfo(cost = NodeCost.UNINITIALIZED)
-    abstract static class UnresolvedWriteLocalFrameVariableNode extends WriteLocalFrameVariableNode {
-
-        public abstract Mode getMode();
-
-        @Specialization
-        protected byte doLogical(VirtualFrame frame, byte value) {
-            resolveAndSet(frame, value, FrameSlotKind.Byte);
-            return value;
-        }
+    private final Mode mode;
 
-        @Specialization
-        protected int doInteger(VirtualFrame frame, int value) {
-            resolveAndSet(frame, value, FrameSlotKind.Int);
-            return value;
-        }
+    private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
+    private final BranchProfile invalidateProfile = BranchProfile.create();
 
-        @Specialization
-        protected double doDouble(VirtualFrame frame, double value) {
-            resolveAndSet(frame, value, FrameSlotKind.Double);
-            return value;
-        }
-
-        @Specialization
-        protected Object doObject(VirtualFrame frame, Object value) {
-            resolveAndSet(frame, value, FrameSlotKind.Object);
-            return value;
-        }
-
-        private void resolveAndSet(VirtualFrame frame, Object value, FrameSlotKind initialKind) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            // it's slow path (unconditional replace) so toString() is fine as well
-            if (getName().toString().isEmpty()) {
-                throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
-            }
-            FrameSlot frameSlot = findOrAddFrameSlot(frame.getFrameDescriptor(), getName(), initialKind);
-            replace(ResolvedWriteLocalFrameVariableNode.create(getRhs(), getName(), frameSlot, getMode())).execute(frame, value);
-        }
+    protected WriteLocalFrameVariableNode(Object name, Mode mode) {
+        super(name);
+        this.mode = mode;
     }
 
-    @NodeFields({@NodeField(name = "frameSlot", type = FrameSlot.class), @NodeField(name = "mode", type = Mode.class)})
-    abstract static class ResolvedWriteLocalFrameVariableNode extends WriteLocalFrameVariableNode {
-
-        private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
-        private final BranchProfile invalidateProfile = BranchProfile.create();
-
-        public abstract Mode getMode();
-
-        private static ResolvedWriteLocalFrameVariableNode create(RNode rhs, Object name, FrameSlot frameSlot, Mode mode) {
-            return ResolvedWriteLocalFrameVariableNodeGen.create(rhs, name, frameSlot, mode);
-        }
+    protected FrameSlot findOrAddFrameSlot(VirtualFrame frame, FrameSlotKind initialKind) {
+        return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), getName(), initialKind);
+    }
 
-        @Specialization(guards = "isLogicalKind(frame, frameSlot)")
-        protected byte doLogical(VirtualFrame frame, FrameSlot frameSlot, byte value) {
-            FrameSlotChangeMonitor.setByteAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
-            return value;
-        }
+    @Specialization(guards = "isLogicalKind(frame, frameSlot)")
+    protected byte doLogical(VirtualFrame frame, byte value,
+                    @Cached("findOrAddFrameSlot(frame, Byte)") FrameSlot frameSlot) {
+        FrameSlotChangeMonitor.setByteAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
+        return value;
+    }
 
-        @Specialization(guards = "isIntegerKind(frame, frameSlot)")
-        protected int doInteger(VirtualFrame frame, FrameSlot frameSlot, int value) {
-            FrameSlotChangeMonitor.setIntAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
-            return value;
-        }
+    @Specialization(guards = "isIntegerKind(frame, frameSlot)")
+    protected int doInteger(VirtualFrame frame, int value,
+                    @Cached("findOrAddFrameSlot(frame, Int)") FrameSlot frameSlot) {
+        FrameSlotChangeMonitor.setIntAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
+        return value;
+    }
 
-        @Specialization(guards = "isDoubleKind(frame, frameSlot)")
-        protected double doDouble(VirtualFrame frame, FrameSlot frameSlot, double value) {
-            FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
-            return value;
-        }
+    @Specialization(guards = "isDoubleKind(frame, frameSlot)")
+    protected double doDouble(VirtualFrame frame, double value,
+                    @Cached("findOrAddFrameSlot(frame, Double)") FrameSlot frameSlot) {
+        FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, frameSlot, value, false, invalidateProfile);
+        return value;
+    }
 
-        @Specialization
-        protected Object doObject(VirtualFrame frame, FrameSlot frameSlot, Object value) {
-            Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), getMode(), false);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile);
-            return value;
-        }
+    @Specialization
+    protected Object doObject(VirtualFrame frame, Object value,
+                    @Cached("findOrAddFrameSlot(frame, Object)") FrameSlot frameSlot) {
+        Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false);
+        FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile);
+        return value;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
index c3d06849facec7118352a5eab003a85c99aa40af..8d5de24ba4a73eccd47637e876f98e21dbec25e5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.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
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.find
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
@@ -35,10 +34,8 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNodeFactory.UnresolvedWriteLocalFrameVariableNodeGen;
 import com.oracle.truffle.r.nodes.access.WriteSuperFrameVariableNodeFactory.ResolvedWriteSuperFrameVariableNodeGen;
 import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -50,8 +47,12 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
 
-    static WriteVariableNode create(String name, RNode rhs, Mode mode) {
-        return new UnresolvedWriteSuperFrameVariableNode(name, rhs, mode);
+    protected WriteSuperFrameVariableNode(Object name) {
+        super(name);
+    }
+
+    static WriteVariableNode create(String name, Mode mode, RNode rhs) {
+        return new UnresolvedWriteSuperFrameVariableNode(name, mode, rhs);
     }
 
     protected abstract void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame);
@@ -63,7 +64,8 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         return value;
     }
 
-    @NodeChildren({@NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class), @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class)})
+    @NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class)
+    @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class)
     protected abstract static class ResolvedWriteSuperFrameVariableNode extends WriteSuperFrameVariableNode {
 
         private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
@@ -72,7 +74,8 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
 
         private final Mode mode;
 
-        public ResolvedWriteSuperFrameVariableNode(Mode mode) {
+        public ResolvedWriteSuperFrameVariableNode(Object name, Mode mode) {
+            super(name);
             this.mode = mode;
         }
 
@@ -105,18 +108,12 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
 
         @Child private RNode rhs;
 
-        private final String name;
         private final Mode mode;
 
-        UnresolvedWriteSuperFrameVariableNode(String name, RNode rhs, Mode mode) {
-            this.rhs = rhs;
-            this.name = name;
+        UnresolvedWriteSuperFrameVariableNode(Object name, Mode mode, RNode rhs) {
+            super(name);
             this.mode = mode;
-        }
-
-        @Override
-        public String getName() {
-            return name;
+            this.rhs = rhs;
         }
 
         @Override
@@ -127,9 +124,6 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         @Override
         public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            if (name.isEmpty()) {
-                throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
-            }
             final WriteSuperFrameVariableNode writeNode;
             if (REnvironment.isGlobalEnvFrame(enclosingFrame)) {
                 /*
@@ -137,11 +131,11 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
                  * in the chain, needs the rhs and enclosingFrame nodes
                  */
                 AccessEnclosingFrameNode enclosingFrameNode = RArguments.getEnclosingFrame(frame) == enclosingFrame ? new AccessEnclosingFrameNode() : null;
-                writeNode = ResolvedWriteSuperFrameVariableNodeGen.create(mode, rhs, enclosingFrameNode,
-                                FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), name, FrameSlotKind.Illegal)), name);
+                writeNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, rhs, enclosingFrameNode,
+                                FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), getName(), FrameSlotKind.Illegal)));
             } else {
-                ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(mode, null, null, FrameSlotNode.create(name), name);
-                writeNode = new WriteSuperFrameVariableConditionalNode(actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(name, null, mode), rhs);
+                ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, null, null, FrameSlotNode.createTemp(getName(), false));
+                writeNode = new WriteSuperFrameVariableConditionalNode(getName(), actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(getName(), mode, null), rhs);
             }
             replace(writeNode).execute(frame, value, enclosingFrame);
         }
@@ -154,7 +148,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
                 execute(frame, value, enclosingFrame);
             } else {
                 // we're in global scope, do a local write instead
-                replace(UnresolvedWriteLocalFrameVariableNodeGen.create(rhs, name, mode)).execute(frame, value);
+                replace(WriteLocalFrameVariableNode.create(getName(), mode, rhs)).execute(frame, value);
             }
         }
     }
@@ -169,17 +163,13 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile();
 
-        WriteSuperFrameVariableConditionalNode(ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) {
+        WriteSuperFrameVariableConditionalNode(Object name, ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) {
+            super(name);
             this.writeNode = writeNode;
             this.nextNode = nextNode;
             this.rhs = rhs;
         }
 
-        @Override
-        public Object getName() {
-            return writeNode.getName();
-        }
-
         @Override
         public RNode getRhs() {
             return rhs;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNodeHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNodeHelper.java
deleted file mode 100644
index 29e9f0bdcc9454eb6a7cbb995c3c5cf64dec9792..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNodeHelper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.access;
-
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * Helper class for the WriteSuperFrame variants. This ought to be a static class in
- * {@link WriteSuperFrameVariableNode} but that causes compilation problems.
- */
-abstract class WriteSuperFrameVariableNodeHelper extends BaseWriteVariableNode {
-
-    public abstract void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame);
-
-    @Override
-    public final Object execute(VirtualFrame frame) {
-        Object value = getRhs().execute(frame);
-        execute(frame, value);
-        return value;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
index d8bd5afed82b97de816a820eeb98558be298999c..9416b60d27eb77218c865980578d564b9467816f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.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
@@ -43,7 +43,15 @@ public abstract class WriteVariableNode extends RNode {
         INVISIBLE
     }
 
-    public abstract Object getName();
+    private final Object name;
+
+    protected WriteVariableNode(Object name) {
+        this.name = name;
+    }
+
+    public final Object getName() {
+        return name;
+    }
 
     public abstract RNode getRhs();
 
@@ -54,27 +62,27 @@ public abstract class WriteVariableNode extends RNode {
      */
     public static WriteVariableNode createArgSave(String name, RNode rhs) {
         if (FastROptions.InvisibleArgs.getBooleanValue()) {
-            return WriteLocalFrameVariableNode.create(name, rhs, Mode.INVISIBLE);
+            return WriteLocalFrameVariableNode.create(name, Mode.INVISIBLE, rhs);
         } else {
-            return WriteLocalFrameVariableNode.create(name, rhs, Mode.REGULAR);
+            return WriteLocalFrameVariableNode.create(name, Mode.REGULAR, rhs);
         }
     }
 
     /**
      * Variant for anonymous variables in the current frame.
      */
-    public static WriteVariableNode createAnonymous(String name, RNode rhs, Mode mode) {
-        return WriteLocalFrameVariableNode.create(name, rhs, mode);
+    public static WriteVariableNode createAnonymous(String name, Mode mode, RNode rhs) {
+        return WriteLocalFrameVariableNode.create(name, mode, rhs);
     }
 
     /**
      * Variant for anonymous variables in either the current or a super frame..
      */
-    public static WriteVariableNode createAnonymous(String name, RNode rhs, Mode mode, boolean isSuper) {
+    public static WriteVariableNode createAnonymous(String name, Mode mode, RNode rhs, boolean isSuper) {
         if (isSuper) {
-            return WriteSuperFrameVariableNode.create(name, rhs, mode);
+            return WriteSuperFrameVariableNode.create(name, mode, rhs);
         } else {
-            return WriteLocalFrameVariableNode.create(name, rhs, mode);
+            return WriteLocalFrameVariableNode.create(name, mode, rhs);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableSyntaxNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableSyntaxNode.java
index 2840ed66f374265a1c1fde8ab516db04997b4b08..39542472910f4529d511bcf59386ff89df3bb67d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableSyntaxNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableSyntaxNode.java
@@ -27,18 +27,19 @@ import static com.oracle.truffle.api.nodes.NodeCost.NONE;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
 import com.oracle.truffle.r.nodes.control.OperatorNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
+/**
+ * This node represents a write to a variable on the syntax level, i.e., in the R source code.
+ */
 @NodeInfo(cost = NONE)
 public final class WriteVariableSyntaxNode extends OperatorNode {
 
@@ -47,25 +48,10 @@ public final class WriteVariableSyntaxNode extends OperatorNode {
 
     private final RSyntaxElement lhs;
 
-    public WriteVariableSyntaxNode(SourceSection source, RSyntaxLookup operator, RSyntaxElement lhs, RNode rhs, boolean isSuper) {
+    public WriteVariableSyntaxNode(SourceSection source, RSyntaxLookup operator, RSyntaxElement lhs, String name, RNode rhs, boolean isSuper) {
         super(source, operator);
         this.lhs = lhs;
-        String name;
-        if (lhs instanceof RSyntaxLookup) {
-            name = ((RSyntaxLookup) lhs).getIdentifier();
-        } else if (lhs instanceof RSyntaxConstant) {
-            RSyntaxConstant c = (RSyntaxConstant) lhs;
-            if (c.getValue() instanceof String) {
-                name = (String) c.getValue();
-            } else {
-                // "this" needs to be initialized for error reporting to work
-                this.write = WriteVariableNode.createAnonymous("dummy", rhs, Mode.REGULAR, isSuper);
-                throw RError.error(this, RError.Message.INVALID_LHS, "do_set");
-            }
-        } else {
-            throw RInternalError.unimplemented("unexpected lhs type in replacement: " + lhs.getClass());
-        }
-        this.write = WriteVariableNode.createAnonymous(name, rhs, Mode.REGULAR, isSuper);
+        this.write = WriteVariableNode.createAnonymous(name, Mode.REGULAR, rhs, isSuper);
         assert write != null;
     }
 
@@ -79,6 +65,21 @@ public final class WriteVariableSyntaxNode extends OperatorNode {
         return write.execute(frame);
     }
 
+    @Override
+    public int executeInteger(VirtualFrame frame) throws UnexpectedResultException {
+        return write.executeInteger(frame);
+    }
+
+    @Override
+    public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
+        return write.executeDouble(frame);
+    }
+
+    @Override
+    public byte executeByte(VirtualFrame frame) throws UnexpectedResultException {
+        return write.executeByte(frame);
+    }
+
     @Override
     public Object visibleExecute(VirtualFrame frame) {
         Object result = write.execute(frame);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
index 11825aaf02cece30f2205fb0ea953ac6e8b5fc73..36f9c1ca7505be6d75c2ac06bde56adb190c2d46 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.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,10 +23,10 @@
 package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
-@NodeChildren({@NodeChild(value = "left", type = RNode.class), @NodeChild(value = "right", type = RNode.class)})
+@NodeChild(value = "left", type = RNode.class)
+@NodeChild(value = "right", type = RNode.class)
 abstract class BinaryNode extends RNode {
 
     protected abstract RNode getLeft();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
index c8825078e76d68f31b940f517fdb52d6e24b0290..d50558d6209356a2ae00089374cf22c521aea35f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
@@ -62,9 +62,9 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
         String rangeName = AnonymousFrameVariable.create("FOR_RANGE");
         String lengthName = AnonymousFrameVariable.create("FOR_LENGTH");
 
-        this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, null, Mode.REGULAR);
-        this.writeRangeNode = WriteVariableNode.createAnonymous(rangeName, range, Mode.REGULAR);
-        this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, RLengthNodeGen.create(ReadVariableNode.create(rangeName)), Mode.REGULAR);
+        this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, Mode.REGULAR, null);
+        this.writeRangeNode = WriteVariableNode.createAnonymous(rangeName, Mode.REGULAR, range);
+        this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, Mode.REGULAR, RLengthNodeGen.create(ReadVariableNode.create(rangeName)));
         this.loopNode = Truffle.getRuntime().createLoopNode(new ForRepeatingNode(this, var.getIdentifier(), body, indexName, lengthName, rangeName));
     }
 
@@ -96,12 +96,12 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
 
         ForRepeatingNode(ForNode forNode, String var, RNode body, String indexName, String lengthName, String rangeName) {
             this.forNode = forNode;
-            this.writeElementNode = WriteVariableNode.createAnonymous(var, createIndexedLoad(indexName, rangeName), Mode.REGULAR, false);
+            this.writeElementNode = WriteVariableNode.createAnonymous(var, Mode.REGULAR, createIndexedLoad(indexName, rangeName), false);
             this.body = body;
 
             this.readIndexNode = ReadVariableNode.create(indexName);
             this.readLengthNode = ReadVariableNode.create(lengthName);
-            this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, null, Mode.REGULAR);
+            this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, Mode.REGULAR, null);
             // pre-initialize the profile so that loop exits to not deoptimize
             conditionProfile.profile(false);
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
index ffd2040d06defe488a671663946a14e366aa3d44..4be2260ed9da5d82cb153bf830b4ef464b134c32 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.nodes.access.WriteVariableSyntaxNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -91,14 +92,36 @@ public final class ReplacementDispatchNode extends OperatorNode {
 
     public RNode create(boolean isVoid) {
         RNode replacement;
-        if (lhs.asRSyntaxNode() instanceof RSyntaxCall) {
+        RSyntaxNode lhsSyntax = lhs.asRSyntaxNode();
+        if (lhsSyntax instanceof RSyntaxCall) {
             replacement = createReplacementNode(isVoid);
         } else {
-            replacement = new WriteVariableSyntaxNode(getLazySourceSection(), operator, lhs.asRSyntaxNode(), rhs, isSuper);
+            replacement = createWriteVariableNode(lhsSyntax);
         }
         return replace(replacement);
     }
 
+    private RNode createWriteVariableNode(RSyntaxNode lhsSyntax) {
+        String name;
+        if (lhsSyntax instanceof RSyntaxLookup) {
+            name = ((RSyntaxLookup) lhsSyntax).getIdentifier();
+        } else if (lhsSyntax instanceof RSyntaxConstant) {
+            RSyntaxConstant c = (RSyntaxConstant) lhsSyntax;
+            if (c.getValue() instanceof String) {
+                name = (String) c.getValue();
+            } else {
+                // "this" needs to be initialized for error reporting to work
+                throw RError.error(this, RError.Message.INVALID_LHS, "do_set");
+            }
+        } else {
+            throw RInternalError.unimplemented("unexpected lhs type in replacement: " + lhsSyntax.getClass());
+        }
+        if (name.isEmpty()) {
+            throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+        }
+        return new WriteVariableSyntaxNode(getLazySourceSection(), operator, lhsSyntax, name, rhs, isSuper);
+    }
+
     @Override
     public ArgumentsSignature getSyntaxSignature() {
         return ArgumentsSignature.empty(2);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 8fea3922499d8129309a55a96d5a685689993d7a..5986bdbb7b83c5648cbb68104b43c0c942287f40 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -174,7 +174,7 @@ abstract class ReplacementNode extends OperatorNode {
             super(source, operator, lhs);
             this.rhs = rhs;
 
-            this.storeRhs = WriteVariableNode.createAnonymous("*rhs*" + tempNamesStartIndex, rhs, WriteVariableNode.Mode.INVISIBLE);
+            this.storeRhs = WriteVariableNode.createAnonymous("*rhs*" + tempNamesStartIndex, WriteVariableNode.Mode.INVISIBLE, rhs);
             this.removeRhs = RemoveAndAnswerNode.create("*rhs*" + tempNamesStartIndex);
         }
 
@@ -368,7 +368,7 @@ abstract class ReplacementNode extends OperatorNode {
             for (int i = calls.size() - 1, tmpIndex = 0; i >= 1; i--, tmpIndex++) {
                 ReadVariableNode newFirstArg = ReadVariableNode.create("*tmp*" + (tempNamesStartIndex + tmpIndex));
                 RNode update = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext);
-                instructions.add(WriteVariableNode.createAnonymous("*tmp*" + (tempNamesStartIndex + tmpIndex + 1), update, WriteVariableNode.Mode.INVISIBLE));
+                instructions.add(WriteVariableNode.createAnonymous("*tmp*" + (tempNamesStartIndex + tmpIndex + 1), WriteVariableNode.Mode.INVISIBLE, update));
             }
             /*
              * Create the update calls, for "a(b(x)) <- z", this would be `a<-` and `b<-`, the
@@ -379,14 +379,14 @@ abstract class ReplacementNode extends OperatorNode {
                 String tmprName = i == 0 ? ("*rhs*" + tempNamesStartIndex) : ("*tmpr*" + (tempNamesStartIndex + i - 1));
                 RNode update = createFunctionUpdate(source, ReadVariableNode.create("*tmp*" + tmpIndex), ReadVariableNode.create(tmprName), calls.get(i), codeBuilderContext);
                 if (i < calls.size() - 1) {
-                    instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesStartIndex + i), update, WriteVariableNode.Mode.INVISIBLE));
+                    instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesStartIndex + i), WriteVariableNode.Mode.INVISIBLE, update));
                 } else {
-                    instructions.add(WriteVariableNode.createAnonymous(targetVarName, update, WriteVariableNode.Mode.REGULAR, isSuper));
+                    instructions.add(WriteVariableNode.createAnonymous(targetVarName, WriteVariableNode.Mode.REGULAR, update, isSuper));
                 }
             }
 
             this.updates = instructions.toArray(new RNode[instructions.size()]);
-            this.targetTmpWrite = WriteVariableNode.createAnonymous(getTargetTmpName(tempNamesStartIndex), target, WriteVariableNode.Mode.INVISIBLE);
+            this.targetTmpWrite = WriteVariableNode.createAnonymous(getTargetTmpName(tempNamesStartIndex), WriteVariableNode.Mode.INVISIBLE, target);
             this.targetTmpRemove = RemoveAndAnswerNode.create(getTargetTmpName(tempNamesStartIndex));
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
index 748dd665f74f59189f17a4bb285a2631bf21adb4..449eabf4bdbd68285bb9edc49a05224efdbef6b9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
@@ -51,10 +51,10 @@ abstract class LoadMethod extends RBaseNode {
     @Child private GetFixedAttributeNode definedAttrAccess = GetFixedAttributeNode.create(RRuntime.R_DEFINED);
     @Child private GetFixedAttributeNode nextMethodAttrAccess = GetFixedAttributeNode.create(RRuntime.R_NEXT_METHOD);
     @Child private GetFixedAttributeNode sourceAttrAccess = GetFixedAttributeNode.create(RRuntime.R_SOURCE);
-    @Child private WriteLocalFrameVariableNode writeRTarget = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_TARGET, null, WriteVariableNode.Mode.REGULAR);
-    @Child private WriteLocalFrameVariableNode writeRDefined = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_DEFINED, null, WriteVariableNode.Mode.REGULAR);
-    @Child private WriteLocalFrameVariableNode writeRNextMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_NEXT_METHOD, null, WriteVariableNode.Mode.REGULAR);
-    @Child private WriteLocalFrameVariableNode writeRMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_METHOD, null, WriteVariableNode.Mode.REGULAR);
+    @Child private WriteLocalFrameVariableNode writeRTarget = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_TARGET, WriteVariableNode.Mode.REGULAR, null);
+    @Child private WriteLocalFrameVariableNode writeRDefined = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_DEFINED, WriteVariableNode.Mode.REGULAR, null);
+    @Child private WriteLocalFrameVariableNode writeRNextMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_NEXT_METHOD, WriteVariableNode.Mode.REGULAR, null);
+    @Child private WriteLocalFrameVariableNode writeRMethod = WriteLocalFrameVariableNode.create(RRuntime.R_DOT_METHOD, WriteVariableNode.Mode.REGULAR, null);
     @Child private LocalReadVariableNode methodsEnvRead = LocalReadVariableNode.create("methods", true);
     @Child private ReadVariableNode loadMethodFind;
     @Child private CallRFunctionNode loadMethodCall;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java
index f4f299fa5e6f591b38bbb5bed7accdbe771d427c..f645d23f52d00e855f51b0d7c639e3258d8755b5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
-import com.oracle.truffle.api.dsl.NodeField;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -30,14 +29,21 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-@NodeField(name = "preserveNonVector", type = boolean.class)
 public abstract class CastToVectorNode extends CastNode {
 
-    public abstract boolean isPreserveNonVector();
+    private final boolean preserveNonVector;
+
+    protected CastToVectorNode(boolean preserveNonVector) {
+        this.preserveNonVector = preserveNonVector;
+    }
+
+    public final boolean isPreserveNonVector() {
+        return preserveNonVector;
+    }
 
     @Specialization
     protected Object castNull(@SuppressWarnings("unused") RNull rnull) {
-        if (isPreserveNonVector()) {
+        if (preserveNonVector) {
             return RNull.instance;
         } else {
             return RDataFactory.createList();
@@ -46,7 +52,7 @@ public abstract class CastToVectorNode extends CastNode {
 
     @Specialization
     protected Object castMissing(@SuppressWarnings("unused") RMissing missing) {
-        if (isPreserveNonVector()) {
+        if (preserveNonVector) {
             return RMissing.instance;
         } else {
             return RDataFactory.createList();
@@ -55,7 +61,7 @@ public abstract class CastToVectorNode extends CastNode {
 
     @Specialization
     protected Object castFunction(RFunction f) {
-        if (isPreserveNonVector()) {
+        if (preserveNonVector) {
             return f;
         } else {
             return RDataFactory.createList();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
index 82b940252a7b6c985cb83f8fa8c35a8b31c1c878..9a4fe5e0466288eefe2b0e64e086afb1beebc916 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.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.unary;
 
 import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.api.dsl.NodeChildren;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
@@ -44,7 +43,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
-@NodeChildren({@NodeChild("operand")})
+@NodeChild("operand")
 public abstract class ConvertBooleanNode extends RNode {
 
     private final NAProfile naProfile = NAProfile.create();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
index 4b20e6deda421058dad2d43c4845b25b74dcb6a0..54d04e8c92348567801b540b933141b02fc5eb73 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
@@ -22,25 +22,26 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
-import com.oracle.truffle.api.dsl.NodeField;
-import com.oracle.truffle.api.dsl.NodeFields;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
-@NodeFields({@NodeField(name = "emptyError", type = RError.Message.class), @NodeField(name = "sizeWarning", type = RError.Message.class), @NodeField(name = "argumentName", type = String.class),
-                @NodeField(name = "defaultValue", type = int.class)})
 public abstract class FirstIntNode extends CastNode {
 
-    protected abstract RError.Message getEmptyError();
+    private final RError.Message emptyError;
+    private final RError.Message sizeWarning;
+    private final String argumentName;
+    private final int defaultValue;
 
-    protected abstract RError.Message getSizeWarning();
-
-    protected abstract String getArgumentName();
-
-    protected abstract int getDefaultValue();
+    protected FirstIntNode(Message emptyError, Message sizeWarning, String argumentName, int defaultValue) {
+        this.emptyError = emptyError;
+        this.sizeWarning = sizeWarning;
+        this.argumentName = argumentName;
+        this.defaultValue = defaultValue;
+    }
 
     public abstract int executeInt(Object value);
 
@@ -55,14 +56,14 @@ public abstract class FirstIntNode extends CastNode {
     @Specialization(replaces = "firstScalar")
     protected int firstVector(RAbstractIntVector argument) {
         if (!lengthOneProfile.profile(argument.getLength() == 1)) {
-            if (getSizeWarning() != null) {
-                RError.warning(this, getSizeWarning(), getArgumentName());
+            if (sizeWarning != null) {
+                RError.warning(this, sizeWarning, argumentName);
                 if (argument.getLength() == 0) {
-                    return getDefaultValue();
+                    return defaultValue;
                 }
-            } else if (getEmptyError() != null && argument.getLength() == 0) {
+            } else if (emptyError != null && argument.getLength() == 0) {
                 errorProfile.enter();
-                throw RError.error(this, getEmptyError(), getArgumentName());
+                throw RError.error(this, emptyError, argumentName);
             }
         }
         return argument.getDataAt(0);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
index ef7bb5c6ddca1326fc7dd531bc40e6028da07f09..a1672bbea11b297a6b12a90dc584590e27cb9335 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
@@ -23,20 +23,22 @@
 package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.NodeField;
-import com.oracle.truffle.api.dsl.NodeFields;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
-@NodeFields({@NodeField(name = "emptyError", type = RError.Message.class), @NodeField(name = "argumentName", type = String.class)})
 public abstract class FirstStringNode extends CastNode {
 
-    protected abstract RError.Message getEmptyError();
+    private final RError.Message emptyError;
+    private final String argumentName;
 
-    protected abstract String getArgumentName();
+    protected FirstStringNode(Message emptyError, String argumentName) {
+        this.emptyError = emptyError;
+        this.argumentName = argumentName;
+    }
 
     private final ConditionProfile lengthOneProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile errorProfile = BranchProfile.create();
@@ -54,14 +56,14 @@ public abstract class FirstStringNode extends CastNode {
     protected String firstVector(RAbstractStringVector argument) {
         if (!lengthOneProfile.profile(argument.getLength() == 1)) {
             errorProfile.enter();
-            throw RError.error(RError.SHOW_CALLER, getEmptyError(), getArgumentName());
+            throw RError.error(RError.SHOW_CALLER, emptyError, argumentName);
         }
         return argument.getDataAt(0);
     }
 
     @Fallback
     protected String firstVectorFallback(@SuppressWarnings("unused") Object argument) {
-        throw RError.error(RError.SHOW_CALLER, getEmptyError(), getArgumentName());
+        throw RError.error(RError.SHOW_CALLER, emptyError, argumentName);
     }
 
     public static FirstStringNode createWithError(RError.Message emptyError, String argumentName) {
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index fad0981f6dd9d10f6fd38521d1b490453b022a5d..527fa89155eb5ea7769b46d68cadb34486156244 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -28,7 +28,7 @@ suite = {
     "suites" : [
             {
                "name" : "truffle",
-               "version" : "ffe6583cc1d92c8e9f7cddd8283c23941faecddc",
+               "version" : "0a9e88293bf90fe485999b26b0969e71509a64aa",
                "urls" : [
                     {"url" : "https://github.com/graalvm/truffle", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},