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 ce0316bf67dada4a8912bcede9e9733098f8901c..80d0e5055eadd9647f0219fceda234d21fdf032a 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 @@ -397,10 +397,17 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { 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(), !false, replacementCall, replacement.isSuper(), replacement.getSource(), (receiver, rhsAccess) -> { + 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); @@ -497,6 +504,18 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { 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(); + } + assert fun.getArguments().size() == 1; + ReadVariableNode function = ReadVariableNode.createForced(null, funName, RType.Function); + return RCallNode.createCall(null, function, ArgumentsSignature.empty(2), this.visit(fun.getArguments().get(0)), rhs); + } + private RSyntaxNode doReplacementLeftHandSide(ASTNode receiver, boolean needsSyntaxAST, RSyntaxNode rhs, boolean isSuper, SourceSection source, BiFunction<RSyntaxNode, RSyntaxNode, RCallNode> updateFunction) { if (receiver.getClass() == FunctionCall.class) { 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 fb7c924e7d67910e02803b2e6e05216ccd01c1f1..810d078fb73c8e095f79b3672f5435959d5a1692 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 @@ -106,13 +106,13 @@ public abstract class AssignVariable extends ASTNode { String builtinName = lhs.getName() + "<-"; lhs.setSymbol(builtinName); } else { - assert false; + 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) { + if (first instanceof SimpleAccessVariable || first instanceof AccessVector || first instanceof FieldAccess || first instanceof FunctionCall) { return new Replacement(src, isSuper, lhs, rhs); } else { // TODO here we need to flatten complex assignments diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 2e009360b4ed9a06bc1c584adc83b7fe1e152369..11428392dba5e08ffefe0e3aee6bf6cb9c1c1035 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -50316,6 +50316,15 @@ Error in foo(1, 2, 3) : unused arguments (2, 3) #{ x <- function(a,b) { a^b } ; g <- function() { x <- "sum" ; f <- function() { sapply(1, x, 2) } ; f() } ; g() } [1] 3 +##com.oracle.truffle.r.test.functions.TestFunctions.testDefinitions +#{ x<-matrix(1:4, ncol=2); y<-list(x=c("a", "b"), y=c("c", "d")); dimnames(x)<-y; names(dimnames(x))<-c("m", "n"); dimnames(x) } +$m +[1] "a" "b" + +$n +[1] "c" "d" + + ##com.oracle.truffle.r.test.functions.TestFunctions.testDefinitionsNamedAndDefault #{ f <- sum ; f(1:10) } [1] 55 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java index f49a6b3ac2d71f446a07c2e255135ae38a97d127..8a83a8bf5720fc64ed215e16ab03abbe026a68f9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java @@ -100,6 +100,7 @@ public class TestFunctions extends TestBase { // replacement function assertEval("{ 'my<-' <- function(x, value) { attr(x, \"myattr\") <- value ; x } ; z <- 1; my(z) <- \"hello\" ; z }"); + assertEval("{ x<-matrix(1:4, ncol=2); y<-list(x=c(\"a\", \"b\"), y=c(\"c\", \"d\")); dimnames(x)<-y; names(dimnames(x))<-c(\"m\", \"n\"); dimnames(x) }"); assertEval("{ x <- function(a,b) { a^b } ; f <- function() { x <- \"sum\" ; sapply(1, x, 2) } ; f() }"); assertEval("{ x <- function(a,b) { a^b } ; g <- function() { x <- \"sum\" ; f <- function() { sapply(1, x, 2) } ; f() } ; g() }");