From a76699a54e2b115cb49d981a12f718165593dd7c Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 12 Jan 2016 17:11:29 +0100
Subject: [PATCH] simpler parsing and AST nodes for replacements

---
 .../truffle/r/nodes/RTruffleVisitor.java      | 374 ++++++------------
 .../r/nodes/control/ReplacementNode.java      |  84 ++--
 .../truffle/r/parser/ParserGeneration.java    |   5 +-
 .../src/com/oracle/truffle/r/parser/R.g       |  30 +-
 .../truffle/r/parser/ast/AccessVariable.java  |  35 +-
 ...nent.java => AccessVariadicComponent.java} |   9 +-
 .../truffle/r/parser/ast/AccessVector.java    |  49 ---
 .../oracle/truffle/r/parser/ast/ArgNode.java  |   8 +-
 .../truffle/r/parser/ast/AssignVariable.java  | 110 ++----
 .../truffle/r/parser/ast/BinaryOperation.java |   4 +-
 .../com/oracle/truffle/r/parser/ast/Call.java |  83 +++-
 .../truffle/r/parser/ast/FieldAccess.java     |  68 ----
 .../truffle/r/parser/ast/FunctionCall.java    |  99 -----
 .../truffle/r/parser/ast/Replacement.java     |  42 +-
 .../parser/ast/SimpleAccessTempVariable.java  |  56 ---
 .../r/parser/ast/SimpleAccessVariable.java    |  50 ---
 .../r/parser/ast/SimpleAssignVariable.java    |  32 --
 .../truffle/r/parser/ast/UpdateField.java     |  54 ---
 .../truffle/r/parser/ast/UpdateVector.java    |  49 ---
 .../oracle/truffle/r/parser/ast/Visitor.java  |  20 +-
 .../truffle/r/parser/tools/BasicVisitor.java  |  33 +-
 .../tools/EvaluatedArgumentsVisitor.java      |  44 +--
 .../truffle/r/parser/tools/PrettyPrinter.java |  32 +-
 .../truffle/r/parser/tools/TreePrinter.java   |  10 +-
 .../truffle/r/runtime/nodes/RBaseNode.java    |  50 +--
 mx.fastr/copyrights/overrides                 |   7 -
 26 files changed, 398 insertions(+), 1039 deletions(-)
 rename com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/{SimpleAccessVariadicComponent.java => AccessVariadicComponent.java} (86%)
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
 delete mode 100644 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
index c19f3fc572..96f4f75c24 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.BiFunction;
 
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
@@ -35,7 +34,6 @@ import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
-import com.oracle.truffle.r.nodes.access.WriteReplacementNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.binary.ColonNode;
@@ -59,16 +57,16 @@ import com.oracle.truffle.r.nodes.function.WrapDefaultArgumentNode;
 import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen;
 import com.oracle.truffle.r.parser.ast.ASTNode;
 import com.oracle.truffle.r.parser.ast.AccessVariable;
-import com.oracle.truffle.r.parser.ast.AccessVector;
+import com.oracle.truffle.r.parser.ast.AccessVariadicComponent;
 import com.oracle.truffle.r.parser.ast.ArgNode;
+import com.oracle.truffle.r.parser.ast.AssignVariable;
 import com.oracle.truffle.r.parser.ast.BinaryOperation;
 import com.oracle.truffle.r.parser.ast.Break;
+import com.oracle.truffle.r.parser.ast.Call;
 import com.oracle.truffle.r.parser.ast.Constant;
-import com.oracle.truffle.r.parser.ast.FieldAccess;
 import com.oracle.truffle.r.parser.ast.For;
 import com.oracle.truffle.r.parser.ast.Formula;
 import com.oracle.truffle.r.parser.ast.Function;
-import com.oracle.truffle.r.parser.ast.FunctionCall;
 import com.oracle.truffle.r.parser.ast.If;
 import com.oracle.truffle.r.parser.ast.Missing;
 import com.oracle.truffle.r.parser.ast.Next;
@@ -76,15 +74,9 @@ import com.oracle.truffle.r.parser.ast.Operation.ArithmeticOperator;
 import com.oracle.truffle.r.parser.ast.Repeat;
 import com.oracle.truffle.r.parser.ast.Replacement;
 import com.oracle.truffle.r.parser.ast.Sequence;
-import com.oracle.truffle.r.parser.ast.SimpleAccessTempVariable;
-import com.oracle.truffle.r.parser.ast.SimpleAccessVariable;
-import com.oracle.truffle.r.parser.ast.SimpleAccessVariadicComponent;
-import com.oracle.truffle.r.parser.ast.SimpleAssignVariable;
 import com.oracle.truffle.r.parser.ast.UnaryOperation;
-import com.oracle.truffle.r.parser.ast.UpdateField;
-import com.oracle.truffle.r.parser.ast.UpdateVector;
+import com.oracle.truffle.r.parser.ast.Visitor;
 import com.oracle.truffle.r.parser.ast.While;
-import com.oracle.truffle.r.parser.tools.BasicVisitor;
 import com.oracle.truffle.r.parser.tools.EvaluatedArgumentsVisitor;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
@@ -99,7 +91,9 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
+public final class RTruffleVisitor implements Visitor<RSyntaxNode> {
+
+    private int tempNamesCount;
 
     public RSyntaxNode transform(ASTNode ast) {
         return ast.accept(this);
@@ -142,7 +136,7 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
     }
 
     @Override
-    public RSyntaxNode visit(FunctionCall call) {
+    public RSyntaxNode visit(Call call) {
         SourceSection callSource = call.getSource();
         List<ArgNode> arguments = call.getArguments();
 
@@ -297,190 +291,154 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
         return new BlockNode(seq.getSource(), rexprs);
     }
 
-    @Override
-    public RSyntaxNode visit(ASTNode n) {
-        throw new UnsupportedOperationException("Unsupported AST Node " + n.getClass().getName());
-    }
-
     @Override
     public RSyntaxNode visit(ArgNode n) {
         assert n.getValue() != null;
         return n.getValue().accept(this);
     }
 
-    private RCallNode createArrayUpdate(List<ArgNode> argList, int argLength, boolean isSubset, RSyntaxNode vector, RSyntaxNode rhs) {
-        RSyntaxNode[] nodes = new RSyntaxNode[Math.max(1, argLength) + 2];
-        String[] names = new String[nodes.length];
-        nodes[0] = vector;
-        if (argLength == 0) {
-            nodes[1] = ConstantNode.create(REmpty.instance);
-        } else {
-            for (int i = 0; i < argLength; i++) {
-                ArgNode node = argList.get(i);
-                if (node.getName() != null) {
-                    names[i + 1] = node.getName();
-                }
-                nodes[i + 1] = node == null ? ConstantNode.create(REmpty.instance) : node.getValue().accept(this);
-            }
+    @Override
+    public RSyntaxNode visit(AssignVariable n) {
+        if (n.getExpr() instanceof Function) {
+            ((Function) n.getExpr()).setDebugName(n.getVariable().toString());
         }
-        nodes[nodes.length - 1] = rhs;
-        names[nodes.length - 1] = "value";
-
-        return RCallNode.createCallNotSyntax(ReadVariableNode.createForcedFunctionLookup(null, isSubset ? "[<-" : "[[<-"), ArgumentsSignature.get(names), nodes);
+        RSyntaxNode expression = n.getExpr().accept(this);
+        return (RSyntaxNode) WriteVariableNode.create(n.getSource(), n.getVariable(), expression.asRNode(), n.isSuper());
     }
 
-    private int tempNamesCount;
-
-    private void resetTempNames() {
-        tempNamesCount = 0;
-    }
+    /**
+     * Creates a call that looks like {@code fun} but has the first argument replaced with
+     * {@code newLhs}.
+     */
+    private RCallNode createFunctionQuery(RSyntaxNode newLhs, Call fun) {
+        assert fun.isSymbol();
+        List<ArgNode> arguments = fun.getArguments();
 
-    private String createTempName() {
-        //@formatter:off
-        // store a - need to use temporary, otherwise there is a failure in case multiple calls to
-        // the replacement form are chained:
-        // x<-c(1); y<-c(1); dim(x)<-1; dim(y)<-1; attr(x, "dimnames")<-(attr(y, "dimnames")<-list("b"))
-        //@formatter:on
-        return "*tmp" + tempNamesCount++ + "*";
-    }
+        RSyntaxNode[] argNodes = new RSyntaxNode[arguments.size()];
+        String[] names = new String[argNodes.length];
+        for (int i = 0; i < arguments.size(); i++) {
+            names[i] = arguments.get(i).getName();
+            argNodes[i] = i == 0 ? newLhs : visit(arguments.get(i));
+        }
 
-    private static ReplacementNode constructReplacementSuffix(RSyntaxNode rhs, RSyntaxNode v, boolean copyRhs, RNode assignFromTemp, String tmpSymbol, String rhsSymbol, SourceSection source) {
-        return new ReplacementNode(source, rhs.asRNode(), v.asRNode(), copyRhs, assignFromTemp, tmpSymbol, rhsSymbol);
+        ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(null, fun.getName());
+        return RCallNode.createCall(fun.getSource(), function, ArgumentsSignature.get(names), argNodes);
     }
 
-    @Override
-    public RSyntaxNode visit(UpdateVector u) {
-        resetTempNames();
-        AccessVector a = u.getVector();
-        int argLength = a.getIndexes().size() - 1;
-        // If recursive no need to set syntaxAST as already handled at top-level
-        return doReplacementLeftHandSide(a.getVector(), true, u.getRHS().accept(this), u.isSuper(), u.getSource(), (receiver, rhsAccess) -> {
-            return createArrayUpdate(a.getIndexes(), argLength, a.isSubset(), receiver, rhsAccess);
-        });
-    }
+    /**
+     * Creates a call that looks like {@code fun}, but has its first argument replaced with
+     * {@code newLhs}, its target turned into an update function ("foo<-"), with the given value
+     * added to the arguments list.
+     */
+    private RCallNode createFunctionUpdate(SourceSection source, RSyntaxNode newLhs, RSyntaxNode rhs, Call fun) {
+        assert fun.isSymbol();
+        List<ArgNode> arguments = fun.getArguments();
 
-    @Override
-    public RSyntaxNode visit(SimpleAssignVariable n) {
-        if (n.getExpr() instanceof Function) {
-            ((Function) n.getExpr()).setDebugName(n.getVariable().toString());
+        RSyntaxNode[] argNodes = new RSyntaxNode[arguments.size() + 1];
+        String[] names = new String[argNodes.length];
+        for (int i = 0; i < arguments.size(); i++) {
+            names[i] = arguments.get(i).getName();
+            argNodes[i] = i == 0 ? newLhs : visit(arguments.get(i));
         }
-        RSyntaxNode expression = n.getExpr().accept(this);
-        return (RSyntaxNode) WriteVariableNode.create(n.getSource(), n.getVariable(), expression.asRNode(), n.isSuper());
-    }
+        argNodes[argNodes.length - 1] = rhs;
+        names[argNodes.length - 1] = "value";
 
-    private RCallNode prepareReplacementCall(FunctionCall f, List<ArgNode> args, String tmpSymbol, String rhsSymbol, boolean simpleReplacement) {
-        // massage arguments to replacement function call (replace v with tmp, append a)
-        List<ArgNode> rfArgs = new ArrayList<>();
-        rfArgs.add(ArgNode.create(null, null, AccessVariable.create(null, tmpSymbol, false)));
-        if (args.size() > 1) {
-            for (int i = 1; i < args.size(); i++) {
-                rfArgs.add(args.get(i));
-            }
+        if (fun.getName().equals("slot")) {
+            // this is pretty gross, but at this point seems like the only way to get setClass to
+            // work properly
+            argNodes[0] = GetNonSharedNodeGen.create(argNodes[0].asRNode());
         }
-        rfArgs.add(ArgNode.create(null, "value", AccessVariable.create(null, rhsSymbol)));
-
-        // replacement function call (use visitor for FunctionCall)
-        FunctionCall rfCall = new FunctionCall(f.getSource(), f.getName(), rfArgs, simpleReplacement);
-        return (RCallNode) visit(rfCall);
+        ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(null, fun.getName() + "<-");
+        return RCallNode.createCall(source, function, ArgumentsSignature.get(names), argNodes);
     }
 
-    //@formatter:off
     /**
-     * Handle an assignment of the form {@code xxx(v) <- a} (or similar, with additional arguments).
-     * These are called "replacements".
+     * This method builds the sequence of calls needed to represent a replacement.<br/>
+     * For example, the replacement {@code a(b(c(x),i),j) <- z} should be decomposed into the
+     * following statements:
      *
-     * According to the R language specification, this corresponds to the following code:
      * <pre>
-     * '*tmp*' <- v
-     * v <- `xxx<-`('*tmp*', a)
-     * rm('*tmp*')
+     * t3 <- x
+     * t2 <- c(t3)
+     * t1 <- b(t2,i)
+     * tt0 <- z
+     * tt1 <- `a<-`(t1, j, tt0) // b(...) with a replaced
+     * tt2 <- `b<-`(t2, i, tt1) // a(...) with b replaced
+     * x <- `c<-`(t3, tt2) // x with c replaced
      * </pre>
-     *
-     * We take an anonymous object to store a, as the anonymous object is unique to this
-     * replacement. This value must be stored as it is the result of the entire replacement expression.
      */
-    //@formatter:on
-    @Override
     public RSyntaxNode visit(Replacement replacement) {
-        resetTempNames();
-        // preparations
-        ASTNode rhsAst = replacement.getExpr();
-        RSyntaxNode rhs = rhsAst.accept(this);
-        FunctionCall fAst = replacement.getReplacementFunctionCall();
-        // fAst has the function name as "x<-" already; we don't want that in the syntaxAST
-        fAst.tempSuppressReplacementSuffix(true);
-        RNode f = fAst.accept(this).asRNode();
-        fAst.tempSuppressReplacementSuffix(false);
-        RSyntaxNode syntaxAST = new WriteReplacementNode((RCallNode) f, rhs);
-        List<ArgNode> args = fAst.getArguments();
-        ASTNode val = args.get(0).getValue();
-        String tmpSymbol = createTempName();
-        RNode assignFromTemp;
-        RSyntaxNode replacementArg;
-        String rhsSymbol = createTempName();
-
-        if (val instanceof SimpleAccessVariable) {
-            SimpleAccessVariable callArg = (SimpleAccessVariable) val;
-            String vSymbol = callArg.getVariable();
-            replacementArg = createReplacementForVariableUsing(callArg, vSymbol, replacement.isSuper());
-            RCallNode replacementCall = prepareReplacementCall(fAst, args, tmpSymbol, rhsSymbol, true);
-            // this is pretty gross, but at this point seems like the only way to get setClass to
-            // work properly
-            if (fAst.getLhs().toString().equals("slot<-")) {
-                replacementCall.replaceArgument(0, GetNonSharedNodeGen.create(replacementCall.getArgument(0).asRNode()));
+        ASTNode lhsAst = replacement.getLhs();
+        ASTNode rhsAst = replacement.getRhs();
+
+        /*
+         * Collect all the function calls in this replacement. For "a(b(x)) <- z", this would be
+         * "a(...)" and "b(...)".
+         */
+        List<Call> calls = new ArrayList<>();
+        ASTNode current = lhsAst;
+        while (!(current instanceof AccessVariable)) {
+            assert current instanceof Call;
+            Call call = (Call) current;
+            calls.add(call);
+
+            if (call.getArguments().isEmpty() || !call.isSymbol()) {
+                // TODO: this should only be signaled when run, not when parsed
+                throw RInternalError.unimplemented("proper error message for RError.INVALID_LHS");
             }
-            assignFromTemp = WriteLocalFrameVariableNode.createAnonymous(vSymbol, replacementCall, WriteVariableNode.Mode.INVISIBLE, replacement.isSuper());
-        } else if (val instanceof AccessVector) {
-            AccessVector callArgAst = (AccessVector) val;
-            replacementArg = callArgAst.accept(this);
-            RCallNode replacementCall = prepareReplacementCall(fAst, args, tmpSymbol, rhsSymbol, false);
-            // see AssignVariable.writeVector (number of args must match)
-            callArgAst.getArguments().add(ArgNode.create(rhsAst.getSource(), "value", rhsAst));
-            RSyntaxNode update = doReplacementLeftHandSide(callArgAst.getVector(), true, replacementCall, replacement.isSuper(), replacement.getSource(), (receiver, rhsAccess) -> {
-                return createArrayUpdate(callArgAst.getIndexes(), callArgAst.getIndexes().size() - 1, callArgAst.isSubset(), receiver, rhsAccess);
-            });
-            assignFromTemp = update.asRNode();
-        } else if (val instanceof FunctionCall) {
-            FunctionCall callArgAst = (FunctionCall) val;
-            replacementArg = callArgAst.accept(this);
-            RCallNode replacementCall = prepareReplacementCall(fAst, args, tmpSymbol, rhsSymbol, false);
-            assignFromTemp = doReplacementLeftHandSide(callArgAst.getArguments().get(0).getValue(), true, replacementCall, replacement.isSuper(), replacement.getSource(), (receiver, rhsAccess) -> {
-                return createFunctionUpdate(rhsAccess, callArgAst);
-            }).asRNode();
-        } else {
-            FieldAccess callArgAst = (FieldAccess) val;
-            replacementArg = callArgAst.accept(this);
-            RCallNode replacementCall = prepareReplacementCall(fAst, args, tmpSymbol, rhsSymbol, false);
-            assignFromTemp = doReplacementLeftHandSide(callArgAst.getLhs(), true, replacementCall, replacement.isSuper(), replacement.getSource(), (receiver, rhsAccess) -> {
-                return createFieldUpdate(null, receiver, rhsAccess, callArgAst.getFieldName(), callArgAst.isAt());
-            }).asRNode();
+            current = call.getArguments().get(0).getValue();
+        }
+        AccessVariable variable = (AccessVariable) current;
+
+        List<RNode> instructions = new ArrayList<>();
+        int tempNamesIndex = tempNamesCount;
+        tempNamesCount += calls.size() + 1;
+
+        /*
+         * Create the calls that extract inner components - only needed for complex replacements
+         * like "a(b(x)) <- z" (where we would extract "b(x)").
+         */
+        for (int i = calls.size() - 1; i >= 1; i--) {
+            RCallNode update = createFunctionQuery(ReadVariableNode.create("*tmp*" + (tempNamesIndex + i + 1)), calls.get(i));
+            instructions.add(WriteVariableNode.createAnonymous("*tmp*" + (tempNamesIndex + i), update, WriteVariableNode.Mode.INVISIBLE));
         }
-        RSyntaxNode result = constructReplacementSuffix(rhs, replacementArg, true, assignFromTemp, tmpSymbol, rhsSymbol, replacement.getSource());
-        ((ReplacementNode) result).setSyntaxAST(syntaxAST);
-        return result;
+        /*
+         * Create the update calls, for "a(b(x)) <- z", this would be `a<-` and `b<-`.
+         */
+        for (int i = 0; i < calls.size(); i++) {
+            RCallNode update = createFunctionUpdate(replacement.getSource(), ReadVariableNode.create("*tmp*" + (tempNamesIndex + i + 1)), ReadVariableNode.create("*tmpr*" + (tempNamesIndex + i - 1)),
+                            calls.get(i));
+            if (i < calls.size() - 1) {
+                instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesIndex + i), update, WriteVariableNode.Mode.INVISIBLE));
+            } else {
+                instructions.add(WriteLocalFrameVariableNode.createAnonymous(variable.getVariable(), update, WriteVariableNode.Mode.INVISIBLE, replacement.isSuper()));
+            }
+        }
+
+        ReadVariableNode variableValue = createReplacementForVariableUsing(variable, replacement.isSuper());
+        ReplacementNode newReplacementNode = new ReplacementNode(replacement.getSource(), replacement.isSuper(), lhsAst.accept(this), rhsAst.accept(this), "*tmpr*" + (tempNamesIndex - 1),
+                        variableValue, "*tmp*" + (tempNamesIndex + calls.size()), instructions);
+
+        tempNamesCount -= calls.size() + 1;
+        return newReplacementNode;
     }
 
-    private static ReadVariableNode createReplacementForVariableUsing(SimpleAccessVariable simpleAccessVariable, String variableSymbol, boolean isSuper) {
+    private static ReadVariableNode createReplacementForVariableUsing(AccessVariable simpleAccessVariable, boolean isSuper) {
         SourceSection argSourceSection = simpleAccessVariable.getSource();
         if (isSuper) {
-            return ReadVariableNode.createSuperLookup(argSourceSection, variableSymbol);
+            return ReadVariableNode.createSuperLookup(argSourceSection, simpleAccessVariable.getVariable());
         } else {
-            return ReadVariableNode.create(argSourceSection, variableSymbol, simpleAccessVariable.shouldCopyValue());
+            return ReadVariableNode.create(argSourceSection, simpleAccessVariable.getVariable(), !isSuper);
         }
     }
 
     @Override
-    public RSyntaxNode visit(SimpleAccessVariable n) {
-        return ReadVariableNode.create(n.getSource(), n.getVariable(), n.shouldCopyValue());
+    public RSyntaxNode visit(AccessVariable n) {
+        return ReadVariableNode.create(n.getSource(), n.getVariable(), false);
     }
 
     @Override
-    public RSyntaxNode visit(SimpleAccessTempVariable n) {
-        return ReadVariableNode.create(n.getSource(), n.getSymbol(), false);
-    }
-
-    @Override
-    public RSyntaxNode visit(SimpleAccessVariadicComponent n) {
+    public RSyntaxNode visit(AccessVariadicComponent n) {
         int ind = n.getIndex();
         return new ReadVariadicComponentNode(n.getSource(), ind > 0 ? ind - 1 : ind);
     }
@@ -524,102 +482,4 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
         RSyntaxNode body = loop.getBody().accept(this);
         return ForNode.create(loop.getSource(), cvar, range, new BlockNode(loop.getBody().getSource(), body));
     }
-
-    @Override
-    public RSyntaxNode visit(FieldAccess access) {
-        SourceSection callSource = access.getSource();
-        RSyntaxNode lhs = access.getLhs().accept(this);
-        ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(callSource, access.isAt() ? "@" : "$");
-        return RCallNode.createCall(callSource, function, ArgumentsSignature.empty(2), lhs, ConstantNode.create(callSource, access.getFieldName()));
-    }
-
-    private static RCallNode createFieldUpdate(SourceSection source, RSyntaxNode receiver, RSyntaxNode rhs, String fieldName, boolean at) {
-        ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(source, at ? "@<-" : "$<-");
-        return RCallNode.createCall(source, function, ArgumentsSignature.empty(3), receiver, ConstantNode.create(source, fieldName), rhs);
-    }
-
-    private RCallNode createFunctionUpdate(RSyntaxNode rhs, FunctionCall fun) {
-        String funName = null;
-        if (fun.isSymbol()) {
-            funName = fun.getName() + "<-";
-        } else {
-            throw RInternalError.unimplemented();
-        }
-        List<ArgNode> arguments = fun.getArguments();
-        String[] names = new String[arguments.size() + 1];
-        RSyntaxNode[] argNodes = new RSyntaxNode[arguments.size() + 1];
-        for (int i = 0; i < arguments.size(); i++) {
-            names[i] = arguments.get(i).getName();
-            argNodes[i] = visit(arguments.get(i));
-        }
-        argNodes[arguments.size()] = rhs;
-        ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(null, funName);
-        return RCallNode.createCall(null, function, ArgumentsSignature.get(names), argNodes);
-    }
-
-    private RSyntaxNode doReplacementLeftHandSide(ASTNode receiver, boolean needsSyntaxAST, RSyntaxNode rhs, boolean isSuper, SourceSection source,
-                    BiFunction<RSyntaxNode, RSyntaxNode, RCallNode> updateFunction) {
-        if (receiver.getClass() == FunctionCall.class) {
-            return updateFunction.apply(receiver.accept(this), rhs);
-        } else {
-            RSyntaxNode result;
-            if (receiver instanceof SimpleAccessVariable) {
-                SimpleAccessVariable varAST = (SimpleAccessVariable) receiver;
-                String vSymbol = varAST.getVariable();
-                ReadVariableNode v = createReplacementForVariableUsing(varAST, vSymbol, isSuper);
-
-                String tmpSymbol = createTempName();
-                String rhsSymbol = createTempName();
-                ReadVariableNode rhsAccess = ReadVariableNode.create(rhsSymbol);
-                ReadVariableNode tmpVarAccess = ReadVariableNode.create(tmpSymbol);
-
-                RSyntaxNode updateOp = updateFunction.apply(tmpVarAccess, rhsAccess);
-                RNode assignFromTemp = WriteVariableNode.createAnonymous(vSymbol, updateOp.asRNode(), WriteVariableNode.Mode.INVISIBLE, isSuper);
-                result = constructReplacementSuffix(rhs, v, false, assignFromTemp, tmpSymbol, rhsSymbol, source);
-            } else if (receiver instanceof AccessVector) {
-                AccessVector vecAST = (AccessVector) receiver;
-                RCallNode updateOp = updateFunction.apply(vecAST.accept(this), rhs);
-                checkAssignSourceSection(updateOp, source);
-                result = doReplacementLeftHandSide(vecAST.getVector(), false, updateOp, isSuper, source, (receiver1, rhsAccess1) -> {
-                    return createArrayUpdate(vecAST.getIndexes(), vecAST.getIndexes().size(), vecAST.isSubset(), receiver1, rhsAccess1);
-                });
-            } else if (receiver instanceof FieldAccess) {
-                FieldAccess accessAST = (FieldAccess) receiver;
-                RCallNode updateOp = updateFunction.apply(accessAST.accept(this), rhs);
-                checkAssignSourceSection(updateOp, source);
-                result = doReplacementLeftHandSide(accessAST.getLhs(), false, updateOp, isSuper, source, (receiver1, rhsAccess1) -> {
-                    return createFieldUpdate(null, receiver1, rhsAccess1, accessAST.getFieldName(), accessAST.isAt());
-                });
-            } else {
-                throw RInternalError.unimplemented();
-            }
-            if (needsSyntaxAST && result instanceof ReplacementNode) {
-                RCallNode update = updateFunction.apply(receiver.accept(this), rhs);
-                RSyntaxNode syntaxAST = update;
-                checkAssignSourceSection(syntaxAST, source);
-                ((ReplacementNode) result).setSyntaxAST(syntaxAST);
-            }
-            return result;
-        }
-    }
-
-    /**
-     * In some cases syntaxAST has acquired a SourceSection during the pre-processing, so we need to
-     * clear it before assigning the "syntactic" source section.
-     */
-    private static void checkAssignSourceSection(RSyntaxNode node, SourceSection source) {
-        node.asRNode().clearSourceSection();
-        node.asRNode().assignSourceSection(source);
-    }
-
-    @Override
-    public RSyntaxNode visit(UpdateField u) {
-        resetTempNames();
-        FieldAccess a = u.getVector();
-        RSyntaxNode rhs = u.getRHS().accept(this);
-        return doReplacementLeftHandSide(a.getLhs(), true, rhs, u.isSuper(), u.getSource(), (receiver, rhsAccess) -> {
-            return createFieldUpdate(u.getSource(), receiver, rhsAccess, a.getFieldName(), a.isAt());
-        });
-    }
-
 }
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 90ae82d7c8..a55fe01a7c 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) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,15 +22,23 @@
  */
 package com.oracle.truffle.r.nodes.control;
 
+import java.util.List;
+
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.r.nodes.access.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.env.*;
-import com.oracle.truffle.r.runtime.nodes.*;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode;
+import com.oracle.truffle.r.nodes.access.WriteVariableNode;
+import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RSerialize;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * Holds the sequence of nodes created for R's replacement assignment. Allows custom deparse and
@@ -42,39 +50,39 @@ public final class ReplacementNode extends RNode implements RSyntaxNode {
      * This holds the AST for the "untransformed" AST, i.e. as it appears in the source. Currently
      * only used in {@code deparse} and {@code serialize}.
      */
-    @CompilationFinal private RSyntaxNode syntaxAST;
+    @CompilationFinal private RSyntaxNode syntaxLhs;
+    private final boolean isSuper;
 
     @Child private WriteVariableNode storeRhs;
     @Child private WriteVariableNode storeValue;
-    @Child private RNode update;
+    @Children private final RNode[] updates;
     @Child private RemoveAndAnswerNode removeTemp;
     @Child private RemoveAndAnswerNode removeRhs;
 
-    public ReplacementNode(SourceSection src, RNode rhs, RNode v, boolean copyRhs, RNode update, String tmpSymbol, String rhsSymbol) {
-        this.storeRhs = WriteVariableNode.createAnonymous(rhsSymbol, rhs, copyRhs ? WriteVariableNode.Mode.COPY : WriteVariableNode.Mode.INVISIBLE);
+    public ReplacementNode(SourceSection src, boolean isSuper, RSyntaxNode syntaxLhs, RSyntaxNode rhs, String rhsSymbol, RNode v, String tmpSymbol, List<RNode> updates) {
+        this.isSuper = isSuper;
+        this.syntaxLhs = syntaxLhs;
+        this.storeRhs = WriteVariableNode.createAnonymous(rhsSymbol, rhs.asRNode(), WriteVariableNode.Mode.INVISIBLE);
         this.storeValue = WriteVariableNode.createAnonymous(tmpSymbol, v, WriteVariableNode.Mode.INVISIBLE);
-        this.update = update;
+        this.updates = updates.toArray(new RNode[updates.size()]);
         // remove var and rhs, returning rhs' value
         this.removeTemp = RemoveAndAnswerNode.create(tmpSymbol);
         this.removeRhs = RemoveAndAnswerNode.create(rhsSymbol);
         assignSourceSection(src);
     }
 
-    public void setSyntaxAST(RSyntaxNode syntaxAST) {
-        // No sharing between syntaxAST and child nodes
-        if (syntaxAST instanceof WriteReplacementNode) {
-            // already taken care of
-            this.syntaxAST = syntaxAST;
-        } else {
-            this.syntaxAST = (RSyntaxNode) NodeUtil.cloneNode(syntaxAST.asNode());
-        }
+    private String getSymbol() {
+        return isSuper ? "<<-" : "<-";
     }
 
     @Override
+    @ExplodeLoop
     public Object execute(VirtualFrame frame) {
         storeRhs.execute(frame);
         storeValue.execute(frame);
-        update.execute(frame);
+        for (RNode update : updates) {
+            update.execute(frame);
+        }
         removeTemp.execute(frame);
         return removeRhs.execute(frame);
     }
@@ -82,18 +90,30 @@ public final class ReplacementNode extends RNode implements RSyntaxNode {
     @Override
     public void deparseImpl(RDeparse.State state) {
         state.startNodeDeparse(this);
-        syntaxAST.deparseImpl(state);
+        syntaxLhs.deparseImpl(state);
+        state.append(' ');
+        state.append(getSymbol());
+        state.append(' ');
+        storeRhs.getRhs().asRSyntaxNode().deparseImpl(state);
         state.endNodeDeparse(this);
     }
 
     @Override
     public void serializeImpl(RSerialize.State state) {
-        syntaxAST.serializeImpl(state);
+        state.setAsLangType();
+        state.setCarAsSymbol(getSymbol());
+        state.openPairList();
+        state.serializeNodeSetCar(syntaxLhs);
+        state.openPairList(SEXPTYPE.LISTSXP);
+        state.serializeNodeSetCar(storeRhs.getRhs());
+        state.setCdr(state.closePairList());
+        state.setCdr(state.closePairList());
     }
 
     @Override
     public RSyntaxNode substituteImpl(REnvironment env) {
-        return syntaxAST.substituteImpl(env);
+        // TODO: implement this correctly
+        return this;
     }
 
     public int getRlengthImpl() {
@@ -102,12 +122,20 @@ public final class ReplacementNode extends RNode implements RSyntaxNode {
 
     @Override
     public Object getRelementImpl(int index) {
-        return RNull.instance;
+        switch (index) {
+            case 0:
+                return RDataFactory.createSymbolInterned(getSymbol());
+            case 1:
+                return RASTUtils.createLanguageElement(syntaxLhs.asRNode());
+            case 2:
+                return RASTUtils.createLanguageElement(storeRhs.getRhs());
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public boolean getRequalsImpl(RSyntaxNode other) {
         throw RInternalError.unimplemented();
     }
-
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
index 51dda64a3f..3e1e4d967e 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -72,6 +72,7 @@ public class ParserGeneration {
         "adapt to RError API change",
         "allow multiple semicolons in {}",
         "allow .. as identifier",
-        "rename Operator class"
+        "rename Operator class",
+        "remove FieldAccess, small refactorings"
     };
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
index 65126f5cf1..2e4c58571c 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
@@ -236,10 +236,10 @@ assign returns [ASTNode v]
         }
     }
     : l=tilde_expr
-      ( ARROW n_ r=expr             { rr = $r.v; $v = AssignVariable.create(null, false, $l.v, $r.v); }
-      | SUPER_ARROW n_ r=expr       { rr = $r.v; $v = AssignVariable.create(null, true, $l.v, $r.v); }
-      | RIGHT_ARROW n_ r=expr       { rr = $r.v; $v = AssignVariable.create(null, false, $r.v, $l.v); }
-      | SUPER_RIGHT_ARROW n_ r=expr { rr = $r.v; $v = AssignVariable.create(null, true, $r.v, $l.v); }
+      ( op=ARROW n_ r=expr             { rr = $r.v; $v = AssignVariable.create(false, sourceSection("assign/ARROW", op), $l.v, $r.v); }
+      | op=SUPER_ARROW n_ r=expr       { rr = $r.v; $v = AssignVariable.create(true, sourceSection("assign/SUPER_ARROW", op), $l.v, $r.v); }
+      | op=RIGHT_ARROW n_ r=expr       { rr = $r.v; $v = AssignVariable.create(false, sourceSection("assign/RIGHT_ARROW", op), $r.v, $l.v); }
+      | op=SUPER_RIGHT_ARROW n_ r=expr { rr = $r.v; $v = AssignVariable.create(true, sourceSection("assign/SUPER_RIGHT_ARROW", op), $r.v, $l.v); }
       | { $v = $l.v; }
       )
     ;
@@ -253,11 +253,11 @@ alter_assign returns [ASTNode v]
         }
     }
     : l=tilde_expr
-      ( (ARROW)=>ARROW n_ r=expr_or_assign                         { rr = $r.v; $v = AssignVariable.create(null, false, $l.v, $r.v); }
-      | (SUPER_ARROW)=>SUPER_ARROW n_ r=expr_or_assign             { rr = $r.v; $v = AssignVariable.create(null, true, $l.v, $r.v); }
-      | (RIGHT_ARROW)=>RIGHT_ARROW n_ r=expr_or_assign             { rr = $r.v; $v = AssignVariable.create(null, false, $r.v, $l.v); }
-      | (SUPER_RIGHT_ARROW)=>SUPER_RIGHT_ARROW n_ r=expr_or_assign { rr = $r.v; $v = AssignVariable.create(null, true, $r.v, $l.v); }
-      | (ASSIGN)=>ASSIGN n_ r=expr_or_assign                       { rr = $r.v; $v = AssignVariable.create(null, false, $l.v, $r.v); }
+      ( (ARROW)=>op=ARROW n_ r=expr_or_assign                         { rr = $r.v; $v = AssignVariable.create(false, sourceSection("assign/ARROW", op), $l.v, $r.v); }
+      | (SUPER_ARROW)=>op=SUPER_ARROW n_ r=expr_or_assign             { rr = $r.v; $v = AssignVariable.create(true, sourceSection("assign/SUPER_ARROW", op), $l.v, $r.v); }
+      | (RIGHT_ARROW)=>op=RIGHT_ARROW n_ r=expr_or_assign             { rr = $r.v; $v = AssignVariable.create(false, sourceSection("assign/RIGHT_ARROW", op), $r.v, $l.v); }
+      | (SUPER_RIGHT_ARROW)=>op=SUPER_RIGHT_ARROW n_ r=expr_or_assign { rr = $r.v; $v = AssignVariable.create(true, sourceSection("assign/SUPER_RIGHT_ARROW", op), $r.v, $l.v); }
+      | (ASSIGN)=>op=ASSIGN n_ r=expr_or_assign                       { rr = $r.v; $v = AssignVariable.create(false, sourceSection("assign/ASSIGN", op), $l.v, $r.v); }
       | { $v = $l.v; }
       )
     ;
@@ -488,20 +488,20 @@ basic_expr returns [ASTNode v]
     ;
 
 expr_subset [ASTNode i] returns [ASTNode v]
-    : (t=FIELD n_ name=id                     { $v = FieldAccess.create(sourceSection("expr_subset/FIELDid", $t, name), FieldOperator.FIELD, i, name.getText()); })
-    | (t=FIELD n_ sname=conststring           { $v = FieldAccess.create(sourceSection("expr_subset/FIELDst", $t, sname), FieldOperator.FIELD, i, sname); })
-    | (t=AT n_ name=id                        { $v = FieldAccess.create(sourceSection("expr_subset/AT", $t, name), FieldOperator.AT, i, name.getText()); })
+    : (t=FIELD n_ name=id                     { $v = Call.create(sourceSection("expr_subset/FIELDid", $t, $y), CallOperator.FIELD, i, Constant.createString(sourceSection("expr_subset/fieldname", name), name.getText())); })
+    | (t=FIELD n_ sname=conststring           { $v = Call.create(sourceSection("expr_subset/FIELDst", $t, $y), CallOperator.FIELD, i, sname); })
+    | (t=AT n_ name=id                        { $v = Call.create(sourceSection("expr_subset/AT", $t, $y), CallOperator.AT, i, Constant.createString(sourceSection("expr_subset/atname", name), name.getText())); })
     | (t=LBRAKET subset=args y=RBRAKET        { $v = Call.create(sourceSection("expr_subset/LBRAKET", $t, $y), CallOperator.SUBSET, i, subset); })
-    | (t=LBB subscript=args RBRAKET y=RBRAKET { $v = Call.create(sourceSection("expr_subset/LBB", $t, $y), CallOperator.SUBSCRIPT, i, subscript); })
     // Must use RBRAKET twice instead of RBB because this is possible: a[b[1]]
+    | (t=LBB subscript=args RBRAKET y=RBRAKET { $v = Call.create(sourceSection("expr_subset/LBB", $t, $y), CallOperator.SUBSCRIPT, i, subscript); })
     | (t=LPAR a=args y=RPAR                   { $v = Call.create(sourceSection("expr_subset/LPAR", $t, $y), i, a); })
     //| { $v = i; }
     ;
 
 simple_expr returns [ASTNode v]
-    : i=id                                      { $v = AccessVariable.create(sourceSection("simple_expr/id", i), i.getText(), false); }
+    : i=id                                      { $v = AccessVariable.create(sourceSection("simple_expr/id", i), i.getText()); }
     | b=bool                                    { $v = b; }
-    | d=DD                                      { $v = AccessVariable.createDotDot(sourceSection("simple_expr/DD", d), d.getText()); }
+    | d=DD                                      { $v = AccessVariadicComponent.create(sourceSection("simple_expr/DD", d), d.getText()); }
     | t=NULL                                    { $v = Constant.createNull(sourceSection("simple_expr/NULL", t)); }
     | t=INF                                     { $v = Constant.createDouble(sourceSection("simple_expr/INF", t), "Inf"); }
     | t=NAN                                     { $v = Constant.createDouble(sourceSection("simple_expr/NAN", t), "NaN"); }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariable.java
index 1cc66bc6ec..d0331e8311 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariable.java
@@ -4,29 +4,46 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
 package com.oracle.truffle.r.parser.ast;
 
+import java.util.Collections;
+import java.util.List;
+
 import com.oracle.truffle.api.source.*;
 
-public abstract class AccessVariable extends ASTNode {
+public final class AccessVariable extends ASTNode {
+
+    private final String variable;
 
-    protected AccessVariable(SourceSection source) {
+    private AccessVariable(SourceSection source, String variable) {
         super(source);
+        this.variable = variable;
+    }
+
+    public String getVariable() {
+        return variable;
+    }
+
+    @Override
+    public int getPrecedence() {
+        return Operation.MAX_PRECEDENCE;
     }
 
-    public static ASTNode create(SourceSection src, String name, boolean shouldCopyValue) {
-        return new SimpleAccessVariable(src, name, shouldCopyValue);
+    @Override
+    public <R> R accept(Visitor<R> v) {
+        return v.visit(this);
     }
 
-    public static ASTNode create(SourceSection src, String tempSymbol) {
-        return new SimpleAccessTempVariable(src, tempSymbol);
+    @Override
+    public <R> List<R> visitAll(Visitor<R> v) {
+        return Collections.emptyList();
     }
 
-    public static ASTNode createDotDot(SourceSection src, String name) {
-        return new SimpleAccessVariadicComponent(src, name);
+    public static ASTNode create(SourceSection src, String name) {
+        return new AccessVariable(src, name);
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariadicComponent.java
similarity index 86%
rename from com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java
rename to com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariadicComponent.java
index f3ef5713b3..8e2c74fc47 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariadicComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -26,12 +26,12 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-public class SimpleAccessVariadicComponent extends AccessVariable {
+public final class AccessVariadicComponent extends ASTNode {
 
     private final int index;
     private final String name;
 
-    SimpleAccessVariadicComponent(SourceSection source, String name) {
+    private AccessVariadicComponent(SourceSection source, String name) {
         super(source);
         index = getVariadicComponentIndex(name);
         this.name = name;
@@ -67,4 +67,7 @@ public class SimpleAccessVariadicComponent extends AccessVariable {
         return Collections.emptyList();
     }
 
+    public static ASTNode create(SourceSection src, String name) {
+        return new AccessVariadicComponent(src, name);
+    }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
deleted file mode 100644
index a0a3535131..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-
-public final class AccessVector extends FunctionCall {
-
-    private final ASTNode vector;
-    private final boolean subset;
-
-    AccessVector(SourceSection source, ASTNode vector, List<ArgNode> arguments, boolean subset) {
-        super(source, subset ? "[" : "[[", arguments);
-        this.vector = vector;
-        this.subset = subset;
-    }
-
-    public ASTNode getVector() {
-        return vector;
-    }
-
-    public boolean isSubset() {
-        return subset;
-    }
-
-    public List<ArgNode> getIndexes() {
-        return super.getArguments().subList(1, super.getArguments().size());
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Arrays.asList(vector.accept(v));
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ArgNode.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ArgNode.java
index 59b9eb515d..ab0abd0085 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ArgNode.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ArgNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,7 +29,7 @@ import com.oracle.truffle.api.source.*;
 public final class ArgNode extends ASTNode {
 
     private final String name;
-    ASTNode value;
+    private ASTNode value;
 
     private ArgNode(SourceSection source, String name, ASTNode value) {
         super(source);
@@ -49,6 +49,10 @@ public final class ArgNode extends ASTNode {
         return value;
     }
 
+    public void setValue(ASTNode value) {
+        this.value = value;
+    }
+
     @Override
     public <R> R accept(Visitor<R> v) {
         return v.visit(this);
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
index d6923b32d7..7ac80eb7d3 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
@@ -15,109 +15,59 @@ import java.util.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.runtime.*;
 
-public abstract class AssignVariable extends ASTNode {
+public final class AssignVariable extends ASTNode {
 
     private final boolean isSuper;
+    private final String variable;
     private final ASTNode rhs;
 
-    protected AssignVariable(SourceSection source, boolean isSuper, ASTNode expr) {
+    private AssignVariable(SourceSection source, boolean isSuper, String variable, ASTNode rhs) {
         super(source);
         this.isSuper = isSuper;
-        this.rhs = expr;
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Arrays.asList(getExpr().accept(v));
-    }
-
-    public ASTNode getExpr() {
-        return rhs;
+        this.variable = variable;
+        this.rhs = rhs;
     }
 
     public boolean isSuper() {
         return isSuper;
     }
 
-    public static ASTNode create(SourceSection src, boolean isSuper, ASTNode lhs, ASTNode rhs) {
-        if (lhs instanceof SimpleAccessVariable) {
-            return writeVariable(src, isSuper, ((SimpleAccessVariable) lhs).getVariable(), rhs);
-        } else if (lhs instanceof SimpleAccessVariadicComponent) {
-            // assigning to ..N indeed creates a local variable of that name
-            return writeVariable(src, isSuper, ((SimpleAccessVariadicComponent) lhs).getName(), rhs);
-        } else if (lhs instanceof AccessVector) {
-            return writeVector(src, isSuper, (AccessVector) lhs, rhs);
-        } else if (lhs instanceof FieldAccess) {
-            return writeField(src, isSuper, (FieldAccess) lhs, rhs);
-        } else if (lhs instanceof FunctionCall) {
-            return writeFunction(src, isSuper, (FunctionCall) lhs, rhs);
-        } else if (lhs instanceof Constant) {
-            Constant c = (Constant) lhs;
-            assert c.getValue() instanceof String;
-            String value = (String) c.getValue();
-            return writeVariable(src, isSuper, value, rhs);
-        }
-        throw RInternalError.unimplemented("unexpected lhs type: " + lhs.getClass());
+    public String getVariable() {
+        return variable;
     }
 
-    private static ASTNode writeVariable(SourceSection src, boolean isSuper, String name, ASTNode rhs) {
-        return new SimpleAssignVariable(src, isSuper, name, rhs);
+    public ASTNode getExpr() {
+        return rhs;
     }
 
-    private static ASTNode writeVector(@SuppressWarnings("unused") SourceSection src, boolean isSuper, AccessVector lhs, ASTNode rhs) {
-        ASTNode first = lhs.getVector();
-        if (first instanceof SimpleAccessVariable) {
-            SimpleAccessVariable simpleAccessVariable = (SimpleAccessVariable) first;
-            AccessVector newLhs = lhs;
-            if (!isSuper) {
-                // ensure the vector is copied from an enclosing frame if it is not found in the
-                // current frame
-                SimpleAccessVariable newAccessVector = new SimpleAccessVariable(simpleAccessVariable.getSource(), simpleAccessVariable.getVariable(), true);
-                newLhs = new AccessVector(lhs.getSource(), newAccessVector, lhs.getArguments(), lhs.isSubset());
-            }
-            UpdateVector update = new UpdateVector(isSuper, newLhs, rhs);
-            lhs.getArguments().add(ArgNode.create(rhs.getSource(), "value", rhs));
-            return update;
-        } else if (first instanceof AccessVector || first instanceof FieldAccess) {
-            UpdateVector update = new UpdateVector(isSuper, lhs, rhs);
-            lhs.getArguments().add(ArgNode.create(rhs.getSource(), "value", rhs));
-            return update;
-        } else if (first instanceof FunctionCall) {
-            FunctionCall replacementFunc = (FunctionCall) first;
-            FunctionCall func = new FunctionCall(replacementFunc.getSource(), replacementFunc.getLhs(), replacementFunc.getArguments(), false);
-            AccessVector newLhs = new AccessVector(func.getSource(), func, lhs.getArguments(), lhs.isSubset());
-            UpdateVector update = new UpdateVector(isSuper, newLhs, rhs);
-            lhs.getArguments().add(ArgNode.create(rhs.getSource(), "value", rhs));
-            return writeFunction(lhs.getSource(), isSuper, replacementFunc, update);
-        } else {
-            // TODO here we need to flatten complex assignments
-            throw RInternalError.unimplemented();
-        }
+    @Override
+    public <R> R accept(Visitor<R> v) {
+        return v.visit(this);
     }
 
-    private static ASTNode writeField(SourceSection src, boolean isSuper, FieldAccess lhs, ASTNode rhs) {
-        return new UpdateField(src, isSuper, lhs, rhs);
+    @Override
+    public <R> List<R> visitAll(Visitor<R> v) {
+        return Arrays.asList(getExpr().accept(v));
     }
 
-    private static ASTNode writeFunction(SourceSection src, boolean isSuper, FunctionCall lhs, ASTNode rhs) {
-        // FIXME Probably we need a special node, for now all assign function should return value
-        if (lhs.isSymbol()) {
-            String builtinName = lhs.getName() + "<-";
-            lhs.setSymbol(builtinName);
+    public static ASTNode create(boolean isSuper, SourceSection operatorSource, ASTNode lhs, ASTNode rhs) {
+        if (lhs instanceof Call) {
+            return Replacement.create(operatorSource, isSuper, lhs, rhs);
         } else {
-            throw RInternalError.unimplemented();
-        }
-        lhs.setAssignment(true);
-        lhs.setSuper(isSuper);
-        if (lhs.getArguments().size() > 0) {
-            ASTNode first = lhs.getArguments().get(0).getValue();
-            if (first instanceof SimpleAccessVariable || first instanceof AccessVector || first instanceof FieldAccess || first instanceof FunctionCall) {
-                return new Replacement(src, isSuper, lhs, rhs);
+            String name;
+            if (lhs instanceof AccessVariable) {
+                name = ((AccessVariable) lhs).getVariable();
+            } else if (lhs instanceof AccessVariadicComponent) {
+                // assigning to ..N indeed creates a local variable of that name
+                name = ((AccessVariadicComponent) lhs).getName();
+            } else if (lhs instanceof Constant) {
+                Constant c = (Constant) lhs;
+                assert c.getValue() instanceof String;
+                name = (String) c.getValue();
             } else {
-                // TODO here we need to flatten complex assignments
-                throw RInternalError.unimplemented("flatten complex assignment: " + (src == null ? "" : src.getCode()));
+                throw RInternalError.unimplemented("unexpected lhs type: " + lhs.getClass());
             }
+            return new AssignVariable(null, isSuper, name, rhs);
         }
-        return lhs;
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
index 94fcab7198..e9a0042302 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -56,7 +56,7 @@ public final class BinaryOperation extends Operation {
                 List<ArgNode> args = new ArrayList<>();
                 args.add(ArgNode.create(left.getSource(), null, left));
                 args.add(ArgNode.create(right.getSource(), null, right));
-                return new FunctionCall(src, op, args);
+                return Call.create(src, op, args);
         }
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
index 42b268ad23..73883114d5 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java
@@ -14,15 +14,44 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-public abstract class Call extends ASTNode {
+public final class Call extends ASTNode {
 
+    // LHS of a call does not need to be a symbol, it can be a lambda expression (FunctionCall)
+    private final Object lhs;
     private final List<ArgNode> arguments;
 
-    protected Call(SourceSection source, List<ArgNode> arguments) {
+    private Call(SourceSection source, Object lhs, List<ArgNode> arguments) {
         super(source);
+        this.lhs = lhs;
         this.arguments = arguments;
     }
 
+    public Object getLhs() {
+        return lhs;
+    }
+
+    public boolean isSymbol() {
+        return lhs instanceof String;
+    }
+
+    public String getName() {
+        String result = (String) lhs;
+        return result;
+    }
+
+    public Call getFunctionCall() {
+        return (Call) lhs;
+    }
+
+    public ASTNode getLhsNode() {
+        return (ASTNode) lhs;
+    }
+
+    @Override
+    public <R> R accept(Visitor<R> v) {
+        return v.visit(this);
+    }
+
     @Override
     public <R> List<R> visitAll(Visitor<R> v) {
         List<R> list = new ArrayList<>();
@@ -39,49 +68,71 @@ public abstract class Call extends ASTNode {
         return arguments;
     }
 
+    public static ASTNode create(SourceSection src, String fun, List<ArgNode> args) {
+        return new Call(src, fun, args);
+    }
+
     public static ASTNode create(SourceSection src, ASTNode call, List<ArgNode> arguments) {
         for (ArgNode a : arguments) {
             // otherwise "empty" indexes are not recorded at all
             if (a.getName() == null && a.getValue() == null) {
-                a.value = new Missing(a.getSource());
+                a.setValue(new Missing(a.getSource()));
             }
         }
         // Add "call"'s source to src
         SourceSection callSrc = combineSource(call.getSource(), src);
-        if (call instanceof SimpleAccessVariable) {
-            SimpleAccessVariable ccall = (SimpleAccessVariable) call;
-            return create(callSrc, ccall.getVariable(), arguments);
+        if (call instanceof AccessVariable) {
+            AccessVariable ccall = (AccessVariable) call;
+            return new Call(callSrc, ccall.getVariable(), arguments);
         } else if (call instanceof Constant) {
             Constant c = (Constant) call;
             assert c.getValue() instanceof String;
-            return create(callSrc, (String) c.getValue(), arguments);
-        } else if (call instanceof FunctionCall) {
-            return new FunctionCall(callSrc, (FunctionCall) call, arguments);
+            return new Call(callSrc, c.getValue(), arguments);
         } else {
-            return new FunctionCall(callSrc, call, arguments, false);
+            return new Call(callSrc, call, arguments);
         }
     }
 
-    public static ASTNode create(SourceSection src, String funName, List<ArgNode> args) {
-        return new FunctionCall(src, funName, args);
+    public static ASTNode create(SourceSection src, CallOperator op, ASTNode lhs, ASTNode... additionalArgs) {
+        List<ArgNode> args = new ArrayList<>();
+        args.add(ArgNode.create(lhs.getSource(), null, lhs));
+        for (ASTNode arg : additionalArgs) {
+            args.add(ArgNode.create(arg.getSource(), null, arg));
+        }
+        return new Call(src, op.getOpName(), args);
     }
 
     public static ASTNode create(SourceSection src, CallOperator op, ASTNode lhs, List<ArgNode> args) {
         for (ArgNode a : args) {
             // otherwise "empty" indexes are not recorded at all
             if (a.getName() == null && a.getValue() == null) {
-                a.value = new Missing(a.getSource());
+                a.setValue(new Missing(a.getSource()));
             }
         }
         // lhs is actually the first argument when rewritten as a call, `[`(lhs, args)
         args.add(0, ArgNode.create(lhs.getSource(), null, lhs));
         // adjust src to encompass the entire expression
         SourceSection newSrc = combineSource(lhs.getSource(), src);
-        return new AccessVector(newSrc, lhs, args, op == CallOperator.SUBSET);
+        if (args.size() == 1) {
+            args.add(ArgNode.create(null, null, new Missing(null)));
+        }
+        return new Call(newSrc, op.getOpName(), args);
     }
 
     public enum CallOperator {
-        SUBSET,
-        SUBSCRIPT
+        SUBSET("["),
+        SUBSCRIPT("[["),
+        FIELD("$"),
+        AT("@");
+
+        private final String opName;
+
+        private CallOperator(String opName) {
+            this.opName = opName;
+        }
+
+        public String getOpName() {
+            return opName;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java
deleted file mode 100644
index d99a968998..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.oracle.truffle.api.source.SourceSection;
-
-public final class FieldAccess extends ASTNode {
-
-    private final ASTNode lhs;
-    private final String fieldName;
-    private final boolean at;
-
-    private FieldAccess(SourceSection source, ASTNode value, String fieldName, boolean at) {
-        super(source);
-        this.lhs = value;
-        this.fieldName = fieldName;
-        this.at = at;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Arrays.asList(lhs.accept(v));
-    }
-
-    public boolean isAt() {
-        return at;
-    }
-
-    public static ASTNode create(SourceSection src, FieldOperator op, ASTNode value, String fieldName) {
-        switch (op) {
-            case AT:
-                return new FieldAccess(src, value, fieldName.intern(), true);
-            case FIELD:
-                return new FieldAccess(src, value, fieldName, false);
-        }
-        throw new Error("No node implemented for: '" + op + "' (" + value + ": " + fieldName + ")");
-    }
-
-    public static ASTNode create(SourceSection src, FieldOperator op, ASTNode value, ASTNode fieldName) {
-        Constant fnc = (Constant) fieldName;
-        assert fnc.getValue() instanceof String;
-        return create(src, op, value, (String) fnc.getValue());
-    }
-
-    public ASTNode getLhs() {
-        return lhs;
-    }
-
-    public String getFieldName() {
-        return fieldName;
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
deleted file mode 100644
index 592da2a875..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class FunctionCall extends Call {
-
-    // LHS of a call does not need to be a symbol, it can be a lambda expression (FunctionCall)
-    private Object lhs;
-    private boolean isAssignment;
-    private boolean isSuper;
-    private final boolean isReplacement;
-    private boolean tempSuppressReplacement;
-
-    public FunctionCall(SourceSection source, Object lhs, List<ArgNode> arguments, boolean isReplacement) {
-        super(source, arguments);
-        this.lhs = lhs;
-        this.isReplacement = isReplacement;
-    }
-
-    FunctionCall(SourceSection src, String funName, List<ArgNode> arguments) {
-        this(src, funName, arguments, false);
-    }
-
-    FunctionCall(SourceSection src, FunctionCall funCall, List<ArgNode> arguments) {
-        this(src, funCall, arguments, false);
-    }
-
-    public Object getLhs() {
-        return lhs;
-    }
-
-    public void setSymbol(String symbol) {
-        lhs = symbol;
-    }
-
-    public boolean isSymbol() {
-        return lhs instanceof String;
-    }
-
-    public String getName() {
-        String result = (String) lhs;
-        if (tempSuppressReplacement) {
-            return result.replace("<-", "");
-        }
-        return result;
-    }
-
-    public FunctionCall getFunctionCall() {
-        return (FunctionCall) lhs;
-    }
-
-    public ASTNode getLhsNode() {
-        return (ASTNode) lhs;
-    }
-
-    public boolean isSuper() {
-        return isSuper;
-    }
-
-    public void setSuper(boolean value) {
-        this.isSuper = value;
-    }
-
-    public boolean isAssignment() {
-        return isAssignment;
-    }
-
-    public void setAssignment(boolean value) {
-        this.isAssignment = value;
-    }
-
-    public boolean isReplacement() {
-        return this.isReplacement;
-    }
-
-    /**
-     * Calls to getName will suppress the "<-" suffix when {@code on == true}.
-     */
-    public void tempSuppressReplacementSuffix(boolean on) {
-        tempSuppressReplacement = on;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
index 5abceb35a6..7d57cd3290 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,19 +22,43 @@
  */
 package com.oracle.truffle.r.parser.ast;
 
-import com.oracle.truffle.api.source.*;
+import java.util.Arrays;
+import java.util.List;
 
-public class Replacement extends AssignVariable {
+import com.oracle.truffle.api.source.SourceSection;
 
-    private final FunctionCall replacementFunctionCall;
+public final class Replacement extends ASTNode {
 
-    Replacement(SourceSection src, boolean isSuper, FunctionCall replacementFunctionCall, ASTNode rhs) {
-        super(src, isSuper, rhs);
-        this.replacementFunctionCall = replacementFunctionCall;
+    private final boolean isSuper;
+    private final ASTNode lhs;
+    private final ASTNode rhs;
+
+    private Replacement(SourceSection source, boolean isSuper, ASTNode lhs, ASTNode rhs) {
+        super(source);
+        this.isSuper = isSuper;
+        this.lhs = lhs;
+        this.rhs = rhs;
+    }
+
+    public static Replacement create(SourceSection source, boolean isSuper, ASTNode lhs, ASTNode rhs) {
+        return new Replacement(source, isSuper, lhs, rhs);
+    }
+
+    public boolean isSuper() {
+        return isSuper;
     }
 
-    public FunctionCall getReplacementFunctionCall() {
-        return replacementFunctionCall;
+    public ASTNode getLhs() {
+        return lhs;
+    }
+
+    public ASTNode getRhs() {
+        return rhs;
+    }
+
+    @Override
+    public <R> List<R> visitAll(Visitor<R> v) {
+        return Arrays.asList(lhs.accept(v), rhs.accept(v));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
deleted file mode 100644
index ce397df492..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.parser.ast;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SimpleAccessTempVariable extends AccessVariable {
-
-    private final String tempSymbol;
-
-    SimpleAccessTempVariable(SourceSection source, String tempSymbol) {
-        super(source);
-        this.tempSymbol = tempSymbol;
-    }
-
-    public String getSymbol() {
-        return tempSymbol;
-    }
-
-    @Override
-    public int getPrecedence() {
-        return Operation.MAX_PRECEDENCE;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Collections.emptyList();
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
deleted file mode 100644
index c95a38430b..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SimpleAccessVariable extends AccessVariable {
-
-    private final String variable;
-    private final boolean shouldCopyValue;
-
-    SimpleAccessVariable(SourceSection source, String variable, boolean shouldCopyValue) {
-        super(source);
-        this.variable = variable;
-        this.shouldCopyValue = shouldCopyValue;
-    }
-
-    public String getVariable() {
-        return variable;
-    }
-
-    @Override
-    public int getPrecedence() {
-        return Operation.MAX_PRECEDENCE;
-    }
-
-    public boolean shouldCopyValue() {
-        return shouldCopyValue;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Collections.emptyList();
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
deleted file mode 100644
index cffd6aa28c..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-public class SimpleAssignVariable extends AssignVariable {
-
-    private final String variable;
-
-    SimpleAssignVariable(SourceSection source, boolean isSuper, String variable, ASTNode rhs) {
-        super(source, isSuper, rhs);
-        this.variable = variable;
-    }
-
-    public String getVariable() {
-        return variable;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
deleted file mode 100644
index e0b38df241..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-
-/**
- * UpdateField AST, for $ operator at top level LHS of assignment.
- */
-public class UpdateField extends ASTNode {
-
-    private final FieldAccess vector;
-    private final ASTNode rhs;
-    private final boolean isSuper;
-
-    UpdateField(SourceSection src, boolean isSuper, FieldAccess vector, ASTNode rhs) {
-        super(src);
-        this.vector = vector;
-        this.rhs = rhs;
-        this.isSuper = isSuper;
-    }
-
-    public FieldAccess getVector() {
-        return vector;
-    }
-
-    public ASTNode getRHS() {
-        return rhs;
-    }
-
-    public boolean isSuper() {
-        return isSuper;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Arrays.asList(rhs.accept(v), vector.accept(v));
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java
deleted file mode 100644
index a38bc4524c..0000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.util.*;
-
-public class UpdateVector extends ASTNode {
-
-    private final AccessVector vector;
-    private final ASTNode rhs;
-    private final boolean isSuper;
-
-    UpdateVector(boolean isSuper, AccessVector vector, ASTNode rhs) {
-        super(null);
-        this.vector = vector;
-        this.rhs = rhs;
-        this.isSuper = isSuper;
-    }
-
-    public AccessVector getVector() {
-        return vector;
-    }
-
-    public ASTNode getRHS() {
-        return rhs;
-    }
-
-    public boolean isSuper() {
-        return isSuper;
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-
-    @Override
-    public <R> List<R> visitAll(Visitor<R> v) {
-        return Arrays.asList(rhs.accept(v), vector.accept(v));
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
index 1e9d7e1a5d..1b5c77a8b3 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -32,25 +32,17 @@ public interface Visitor<R> {
 
     R visit(Constant constant);
 
-    R visit(SimpleAccessVariable readVariable);
+    R visit(AccessVariable readVariable);
 
-    R visit(SimpleAccessTempVariable readVariable);
+    R visit(AccessVariadicComponent readVariable);
 
-    R visit(SimpleAccessVariadicComponent readVariable);
+    R visit(AssignVariable assign);
 
-    R visit(FieldAccess fieldAccess);
-
-    R visit(SimpleAssignVariable assign);
-
-    R visit(Replacement assign);
-
-    R visit(UpdateVector update);
-
-    R visit(UpdateField update);
+    R visit(Replacement replacement);
 
     R visit(Function function);
 
-    R visit(FunctionCall functionCall);
+    R visit(Call functionCall);
 
     R visit(ArgNode arg);
 
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
index 1576f92aca..9fe5257b1a 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -73,27 +73,17 @@ public class BasicVisitor<R> implements Visitor<R> {
     }
 
     @Override
-    public R visit(SimpleAccessVariable n) {
+    public R visit(AccessVariable n) {
         return visit((ASTNode) n);
     }
 
     @Override
-    public R visit(SimpleAccessTempVariable n) {
+    public R visit(AccessVariadicComponent n) {
         return visit((ASTNode) n);
     }
 
     @Override
-    public R visit(SimpleAccessVariadicComponent n) {
-        return visit((ASTNode) n);
-    }
-
-    @Override
-    public R visit(FieldAccess n) {
-        return visit((ASTNode) n);
-    }
-
-    @Override
-    public R visit(SimpleAssignVariable n) {
+    public R visit(AssignVariable n) {
         return visit((ASTNode) n);
     }
 
@@ -102,25 +92,10 @@ public class BasicVisitor<R> implements Visitor<R> {
         return visit((ASTNode) n);
     }
 
-    @Override
-    public R visit(UpdateVector u) {
-        return visit((ASTNode) u);
-    }
-
-    @Override
-    public R visit(UpdateField u) {
-        return visit((ASTNode) u);
-    }
-
     public R visit(Call n) {
         return visit((ASTNode) n);
     }
 
-    @Override
-    public R visit(FunctionCall n) {
-        return visit((Call) n);
-    }
-
     @Override
     public R visit(Function n) {
         return visit((ASTNode) n);
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/EvaluatedArgumentsVisitor.java
index 4afd5b67e5..3360797443 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/EvaluatedArgumentsVisitor.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/EvaluatedArgumentsVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -75,8 +75,8 @@ final class Info {
 
 public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
 
-    private static final Set<String> wellKnownFunctions = new HashSet<>(Arrays.asList("any", "dim", "dimnames", "is.null", "list", "names", "return", "print", "length", "rep", "max", "matrix",
-                    "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "as.integer", ".Call", "sum", "order", "rev", "integer", "double"));
+    private static final Set<String> wellKnownFunctions = new HashSet<>(Arrays.asList("$", "@", "[", "any", "dim", "dimnames", "is.null", "list", "names", "return", "print", "length", "rep", "max",
+                    "matrix", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "as.integer", ".Call", "sum", "order", "rev", "integer", "double"));
 
     private EvaluatedArgumentsVisitor() {
         // private constructor
@@ -98,7 +98,7 @@ public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
     }
 
     @Override
-    public Info visit(SimpleAccessVariadicComponent n) {
+    public Info visit(AccessVariadicComponent n) {
         return Info.EMPTY;
     }
 
@@ -107,11 +107,6 @@ public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
         return Info.EMPTY;
     }
 
-    @Override
-    public Info visit(SimpleAccessTempVariable n) {
-        return Info.EMPTY;
-    }
-
     @Override
     public Info visit(Sequence n) {
         ASTNode[] exprs = n.getExpressions();
@@ -186,7 +181,7 @@ public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
     }
 
     @Override
-    public Info visit(SimpleAssignVariable n) {
+    public Info visit(AssignVariable n) {
         if (n.isSuper()) {
             return Info.ANY;
         } else {
@@ -197,28 +192,20 @@ public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
         }
     }
 
-    @Override
-    public Info visit(UpdateVector n) {
-        Info info = Info.createNew();
-        info.addBefore(n.getRHS().accept(this));
-        info.addBefore(n.getVector().accept(this));
-        return info;
-    }
-
     @Override
     public Info visit(Replacement n) {
         if (n.isSuper()) {
             return Info.ANY;
         } else {
             Info info = Info.createNew();
-            info.addBefore(n.getReplacementFunctionCall().accept(this));
-            info.addBefore(n.getExpr().accept(this));
+            info.addBefore(n.getLhs().accept(this));
+            info.addBefore(n.getRhs().accept(this));
             return info;
         }
     }
 
     @Override
-    public Info visit(FunctionCall n) {
+    public Info visit(Call n) {
         if (n.getLhs() instanceof String && wellKnownFunctions.contains(n.getLhs())) {
             List<ArgNode> arguments = n.getArguments();
             Info info = Info.createNew();
@@ -239,25 +226,12 @@ public final class EvaluatedArgumentsVisitor extends BasicVisitor<Info> {
     }
 
     @Override
-    public Info visit(SimpleAccessVariable n) {
+    public Info visit(AccessVariable n) {
         Info info = Info.createNew();
         info.evaluatedNames.add(n.getVariable());
         return info;
     }
 
-    @Override
-    public Info visit(FieldAccess n) {
-        return n.getLhs().accept(this);
-    }
-
-    @Override
-    public Info visit(UpdateField n) {
-        Info info = Info.createNew();
-        info.addBefore(n.getRHS().accept(this));
-        info.addBefore(n.getVector().accept(this));
-        return info;
-    }
-
     public static FastPathFactory process(Function func) {
         Info info = func.getBody().accept(new EvaluatedArgumentsVisitor());
         boolean[] forcedArgument = new boolean[func.getSignature().size()];
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
index fcb6fe33d4..4ecd2efcc6 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -211,7 +211,7 @@ public class PrettyPrinter extends BasicVisitor<Void> {
     }
 
     @Override
-    public Void visit(SimpleAssignVariable n) {
+    public Void visit(AssignVariable n) {
         print(n.getVariable());
         print(" <- ");
         n.getExpr().accept(this);
@@ -219,15 +219,7 @@ public class PrettyPrinter extends BasicVisitor<Void> {
     }
 
     @Override
-    public Void visit(UpdateVector n) {
-        print(n.getVector());
-        print(" <- ");
-        print(n.getRHS());
-        return null;
-    }
-
-    @Override
-    public Void visit(FunctionCall n) {
+    public Void visit(Call n) {
         print(n.getName() + "(");
         print(n.getArguments(), true);
         print(")");
@@ -244,27 +236,11 @@ public class PrettyPrinter extends BasicVisitor<Void> {
     }
 
     @Override
-    public Void visit(SimpleAccessVariable n) {
+    public Void visit(AccessVariable n) {
         print(n.getVariable());
         return null;
     }
 
-    @Override
-    public Void visit(FieldAccess n) {
-        print(n.getLhs());
-        print("$");
-        print(n.getFieldName());
-        return null;
-    }
-
-    @Override
-    public Void visit(UpdateField n) {
-        n.getVector().accept(this);
-        print(" <- ");
-        n.getRHS().accept(this);
-        return null;
-    }
-
     private void print(List<ArgNode> alist, boolean isCall) {
         boolean f = true;
         for (ArgNode arg : alist) {
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/TreePrinter.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/TreePrinter.java
index b675d7012f..8a9d6b7ff7 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/TreePrinter.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/TreePrinter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -52,10 +52,10 @@ public class TreePrinter extends BasicVisitor<Void> {
         out.print(n.getClass().getSimpleName());
         if (n instanceof BinaryOperation) {
             out.print(" " + ((BinaryOperation) n).getOperator().getName());
-        } else if (n instanceof SimpleAccessVariable) {
-            out.print(" " + ((SimpleAccessVariable) n).getVariable());
-        } else if (n instanceof FunctionCall) {
-            FunctionCall call = (FunctionCall) n;
+        } else if (n instanceof AccessVariable) {
+            out.print(" " + ((AccessVariable) n).getVariable());
+        } else if (n instanceof Call) {
+            Call call = (Call) n;
             out.print(" " + call.getLhs());
         }
         out.println();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index 4ead587ca9..6bac2fb352 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -23,12 +23,14 @@
 package com.oracle.truffle.r.runtime.nodes;
 
 import com.oracle.truffle.api.instrument.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.RDeparse.*;
-import com.oracle.truffle.r.runtime.context.*;
-import com.oracle.truffle.r.runtime.env.*;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeVisitor;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.RDeparse.State;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RSerialize;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * This class should be used as the superclass for all instances of nodes in the FastR AST in
@@ -96,10 +98,6 @@ public abstract class RBaseNode extends Node {
      * found by following the parent chain, which is therefore the default implementation.
      */
     protected RSyntaxNode getRSyntaxNode() {
-        RSyntaxNode node = checkReplacementChild();
-        if (node != null) {
-            return node;
-        }
         Node current = this;
         while (current != null) {
             if (current instanceof RSyntaxNode && ((RSyntaxNode) current).isSyntax()) {
@@ -148,13 +146,6 @@ public abstract class RBaseNode extends Node {
         }
         /* Explicitly allow on a node for which isSyntax() == false */
         if (this instanceof RSyntaxNode) {
-            if (RContext.getRRuntimeASTAccess().isReplacementNode(this)) {
-                return super.getSourceSection();
-            }
-            RSyntaxNode node = checkReplacementChild();
-            if (node != null) {
-                return node.getSourceSection();
-            }
             return super.getSourceSection();
         } else {
             throw RInternalError.shouldNotReachHere("getSourceSection on non-syntax node");
@@ -198,27 +189,4 @@ public abstract class RBaseNode extends Node {
     public SourceSection getEncapsulatingSourceSection() {
         return getRSyntaxNode().getSourceSection();
     }
-
-    /**
-     * This is rather nasty, but then that applies to {@code ReplacementNode} in general. Since a
-     * auto-generated child of a {@code ReplacementNode} may have a {@link SourceSection}, we might
-     * return it using the normal logic, but that would be wrong, we really need to return the the
-     * {@link SourceSection} of the {@code ReplacementNode} itself. This is a case where we can't
-     * use {@link #getRSyntaxNode} as a workaround because the {@code ReplacementNode} child nodes
-     * are just standard {@link RSyntaxNode}s.
-     *
-     * @return {@code null} if not a child of a {@code ReplacementNode}, otherwise the
-     *         {@code ReplacementNode}.
-     */
-    private RSyntaxNode checkReplacementChild() {
-        Node node = this;
-        while (node != null) {
-            if (RContext.getRRuntimeASTAccess().isReplacementNode(node)) {
-                return (RSyntaxNode) node;
-            }
-            node = node.getParent();
-        }
-        return null;
-    }
-
 }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 8b4aff552f..b5978e2f24 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -168,7 +168,6 @@ com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTDeparse.ja
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java,purdue.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVariable.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ASTNode.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java,purdue.copyright
@@ -176,22 +175,16 @@ com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Break.java,purdu
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Call.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ControlStatement.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldAccess.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FieldOperator.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/For.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Function.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/If.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Loop.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Next.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Operation.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Repeat.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sequence.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryOperation.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java,purdue.copyright
-com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/While.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java,purdue.copyright
-- 
GitLab