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