diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index b54a820393bb132f83e78131f2a0169a4af0bd8c..9cd3ced303bce6c8a067230865ee612f636e7883 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -893,7 +893,7 @@ public class RDeparse { } lbreak = linebreak(lbreak); if (snames != null) { - append(snames.getDataAt(i)); + append(quotify(snames.getDataAt(i), '\"')); append(" = "); } appendValue(v.getDataAtAsObject(i)); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java index 21a0d9b77a7c50ebbcb146afdc853e096509ce1f..aa4108bd0360cd282c4e4cc2b35a642c0a56bba0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,9 +87,11 @@ public class RSubstitute { * <li>..., replace by contents of ... (if bound)</li> * </ul> */ - private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment env) { + private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment callEnv) { return new RSyntaxVisitor<T>() { + REnvironment env = callEnv; + @Override protected T visit(RSyntaxCall element) { RSyntaxElement lhs = element.getSyntaxLHS(); @@ -134,8 +136,19 @@ public class RSubstitute { } RArgsValuesAndNames dots = (RArgsValuesAndNames) substitute; for (int j = 0; j < dots.getLength(); j++) { - RSyntaxElement contents = substituteElement(dots.getArgument(j)); - args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + Object dotArg = dots.getArgument(j); + RSyntaxElement contents = substituteElement(dotArg); + if (dotArg instanceof RPromise) { + // Replace the environment used to substitute symbols in a + // promise by the empty one to prevent an infinite recursion + // if the promise contains a vararg + REnvironment origEnv = env; + env = REnvironment.emptyEnv(); + args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + env = origEnv; + } else { + args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + } } continue; } 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 492004a017ebcd486b15ecc4a2902cf9172876d3..07a17a4a9406b0c87695964980e93db2d8bd726d 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 @@ -17032,6 +17032,10 @@ Error in print(x, y) : #deparse(c(T, F)) [1] "c(TRUE, FALSE)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# +#deparse(list(`x y`=1)) +[1] "structure(list(\"x y\" = 1), .Names = \"x y\")" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(quote(1/0)) [1] "1/0" @@ -76378,6 +76382,10 @@ Error in f(10) : ..1 used in an incorrect context, no ... to look in [1] FALSE [1] "bar" +##com.oracle.truffle.r.test.functions.TestFunctions.testDots# +#{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat("Here:"); f1(f2(a, ...)) }; f1(f3("aaa")) } +Here:[1] TRUE + ##com.oracle.truffle.r.test.functions.TestFunctions.testDots# #{ f<-function(...) print(attributes(list(...))); f(a=7) } $names diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java index 04bb15c4d30234d1353cb3f6f3a76975e1d9aca6..41c068ab4ad3c20f8c4a383cb09192b1b70eba58 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java @@ -317,6 +317,8 @@ public class TestBuiltin_deparse extends TestBase { assertEval("deparse(quote(1/0))"); assertEval("e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e"); + + assertEval("deparse(list(`x y`=1))"); } @Test 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 c2ad5d425055a870576bbe188f563d704048f1ca..8265d0daad743fd31606eca36322bfbe3c7629ab 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 @@ -341,6 +341,8 @@ public class TestFunctions extends TestBase { assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ...,,,) } ; g(1) }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }"); + + assertEval("{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat(\"Here:\"); f1(f2(a, ...)) }; f1(f3(\"aaa\")) }"); } @Test