diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java index 797c096ae9a022fd1f8d599e86b0ca240619bd9b..46906aeebc5ce7b0133ff4eef73a250d0baef3a8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.WriteVariableSyntaxNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; @@ -158,16 +157,7 @@ public final class ReplacementDispatchNode extends OperatorNode { current = call.getSyntaxArguments()[0]; } RSyntaxLookup variable = (RSyntaxLookup) current; - ReadVariableNode varRead = createReplacementForVariableUsing(variable, isSuper); - return ReplacementNode.create(getLazySourceSection(), operator, varRead, lhs.asRSyntaxNode(), rhs, calls, variable.getIdentifier(), isSuper, tempNamesStartIndex, isVoid); - } - - private static ReadVariableNode createReplacementForVariableUsing(RSyntaxLookup var, boolean isSuper) { - if (isSuper) { - return ReadVariableNode.createSuperLookup(var.getLazySourceSection(), var.getIdentifier()); - } else { - return ReadVariableNode.create(var.getLazySourceSection(), var.getIdentifier(), true); - } + return ReplacementNode.create(getLazySourceSection(), operator, variable, lhs.asRSyntaxNode(), rhs, calls, isSuper, tempNamesStartIndex, isVoid); } /* 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 ca56335a05ff1e8ee2ae11e192a9e19829cdfc22..284ebf3436c1618a1eb5833555b8b75403c78a03 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 @@ -35,6 +35,7 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.PeekLocalVariableNode; import com.oracle.truffle.r.nodes.function.RCallSpecialNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.GetNonSharedNode; @@ -65,8 +66,8 @@ abstract class ReplacementNode extends OperatorNode { return RContext.getASTBuilder().process(this).asRNode(); } - public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, - String targetVarName, boolean isSuper, int tempNamesStartIndex, boolean isVoid) { + public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, + boolean isSuper, int tempNamesStartIndex, boolean isVoid) { CompilerAsserts.neverPartOfCompilation(); // Note: if specials are turned off in FastR, onlySpecials will never be true boolean createSpecial = hasOnlySpecialCalls(calls); @@ -76,12 +77,12 @@ abstract class ReplacementNode extends OperatorNode { * special call for "replace". */ if (isVoid) { - return new SpecialVoidReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex); + return new SpecialVoidReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex); } else { - return new SpecialReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex); + return new SpecialReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex); } } else { - return new GenericReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex); + return new GenericReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex); } } @@ -163,6 +164,14 @@ abstract class ReplacementNode extends OperatorNode { return null; } + private static RNode createReplacementTarget(RSyntaxLookup variable, boolean isSuper, boolean localPeek) { + if (isSuper) { + return ReadVariableNode.createSuperLookup(variable.getLazySourceSection(), variable.getIdentifier()); + } else { + return localPeek ? new PeekLocalVariableNode(variable.getIdentifier()) : ReadVariableNode.create(variable.getLazySourceSection(), variable.getIdentifier(), true); + } + } + private abstract static class ReplacementWithRhsNode extends ReplacementNode { @Child private WriteVariableNode storeRhs; @@ -226,15 +235,12 @@ abstract class ReplacementNode extends OperatorNode { private final List<RSyntaxCall> calls; private final int tempNamesStartIndex; private final boolean isSuper; - private final String targetVarName; - private final RNode target; + private final RSyntaxLookup variable; - SpecialReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, - boolean isSuper, int tempNamesStartIndex) { + SpecialReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper, int tempNamesStartIndex) { super(source, operator, lhs, rhs, tempNamesStartIndex); - this.target = target; + this.variable = variable; this.calls = calls; - this.targetVarName = targetVarName; this.isSuper = isSuper; this.tempNamesStartIndex = tempNamesStartIndex; @@ -242,7 +248,7 @@ abstract class ReplacementNode extends OperatorNode { * Creates a replacement that consists only of {@link RCallSpecialNode} calls. */ CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + 2); - RNode extractFunc = target; + RNode extractFunc = createReplacementTarget(variable, isSuper, true); for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); @@ -261,7 +267,7 @@ abstract class ReplacementNode extends OperatorNode { replaceCall.execute(frame); } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); - replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls, targetVarName, isSuper, + replace(new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls, isSuper, tempNamesStartIndex)).executeReplacement(frame); } } @@ -280,16 +286,14 @@ abstract class ReplacementNode extends OperatorNode { private final List<RSyntaxCall> calls; private final int tempNamesStartIndex; private final boolean isSuper; - private final String targetVarName; - private final RNode target; + private final RSyntaxLookup variable; - SpecialVoidReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, - boolean isSuper, int tempNamesStartIndex) { + SpecialVoidReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper, + int tempNamesStartIndex) { super(source, operator, lhs); - this.target = target; + this.variable = variable; this.rhs = rhs; this.calls = calls; - this.targetVarName = targetVarName; this.isSuper = isSuper; this.tempNamesStartIndex = tempNamesStartIndex; @@ -297,7 +301,7 @@ abstract class ReplacementNode extends OperatorNode { * Creates a replacement that consists only of {@link RCallSpecialNode} calls. */ CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + 2); - RNode extractFunc = target; + RNode extractFunc = createReplacementTarget(variable, isSuper, true); for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); @@ -309,8 +313,8 @@ abstract class ReplacementNode extends OperatorNode { @Override public Object execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreterAndInvalidate(); - GenericReplacementNode replacement = new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls, - targetVarName, isSuper, tempNamesStartIndex); + GenericReplacementNode replacement = new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls, + isSuper, tempNamesStartIndex); return replace(replacement).execute(frame); } @@ -324,8 +328,9 @@ abstract class ReplacementNode extends OperatorNode { replaceCall.execute(frame); } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); - GenericReplacementNode replacement = replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), - calls, targetVarName, isSuper, tempNamesStartIndex)); + GenericReplacementNode replacement = replace( + new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), + calls, isSuper, tempNamesStartIndex)); if (e.rhsValue == null) { // we haven't queried the rhs value yet @@ -352,8 +357,7 @@ abstract class ReplacementNode extends OperatorNode { @Children private final WriteVariableNode[] updates; - GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper, - int tempNamesStartIndex) { + GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper, int tempNamesStartIndex) { super(source, operator, lhs, rhs, tempNamesStartIndex); /* * When there are more than two function calls in LHS, then we save some function calls @@ -363,6 +367,7 @@ abstract class ReplacementNode extends OperatorNode { CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + calls.size() + 1); int targetIndex = tempNamesStartIndex; + RNode target = createReplacementTarget(variable, isSuper, false); instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(target, calls.get(calls.size() - 1)))); /* * Create the calls that extract inner components - only needed for complex replacements @@ -387,7 +392,7 @@ abstract class ReplacementNode extends OperatorNode { if (i < calls.size() - 1) { instructions.add(WriteVariableNode.createAnonymous(getRHSTemp(++replacementIndex), WriteVariableNode.Mode.INVISIBLE, update)); } else { - instructions.add(WriteVariableNode.createAnonymous(targetVarName, WriteVariableNode.Mode.REGULAR, update, isSuper)); + instructions.add(WriteVariableNode.createAnonymous(variable.getIdentifier(), WriteVariableNode.Mode.REGULAR, update, isSuper)); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java new file mode 100644 index 0000000000000000000000000000000000000000..6ee9ad6abffc088c26d921c5b8a0c0d3f768992e --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java @@ -0,0 +1,94 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.nodes.function; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; + +public final class PeekLocalVariableNode extends RNode implements RSyntaxNode, RSyntaxLookup { + + @Child private LocalReadVariableNode read; + @Child private SetVisibilityNode visibility; + + private final ValueProfile valueProfile = ValueProfile.createClassProfile(); + + public PeekLocalVariableNode(String name) { + this.read = LocalReadVariableNode.create(Utils.intern(name), true); + } + + @Override + public Object execute(VirtualFrame frame) { + Object value = read.execute(frame); + if (value == null) { + throw RSpecialFactory.throwFullCallNeeded(); + } + return valueProfile.profile(value); + } + + @Override + public Object visibleExecute(VirtualFrame frame) { + try { + return execute(frame); + } finally { + if (visibility == null) { + CompilerDirectives.transferToInterpreter(); + visibility = insert(SetVisibilityNode.create()); + } + visibility.execute(frame, true); + } + } + + @Override + public void setSourceSection(SourceSection source) { + // nothing to do + } + + @Override + public String getIdentifier() { + return (String) read.getIdentifier(); + } + + @Override + public boolean isFunctionLookup() { + return false; + } + + @Override + public SourceSection getSourceSection() { + return null; + } + + @Override + public SourceSection getLazySourceSection() { + return null; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java index 31cb895142930c6a530ad3597cf778573046127e..98a793a0147a1f032e48fafd264fc5299d5874e0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java @@ -32,9 +32,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; @@ -43,7 +41,6 @@ import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RVisibility; -import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.context.RContext; @@ -57,60 +54,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { - - @Child private LocalReadVariableNode read; - @Child private SetVisibilityNode visibility; - - private final ValueProfile valueProfile = ValueProfile.createClassProfile(); - - PeekLocalVariableNode(String name) { - this.read = LocalReadVariableNode.create(Utils.intern(name), true); - } - - @Override - public Object execute(VirtualFrame frame) { - Object value = read.execute(frame); - if (value == null) { - throw RSpecialFactory.throwFullCallNeeded(); - } - return valueProfile.profile(value); - } - - @Override - public Object visibleExecute(VirtualFrame frame) { - try { - return execute(frame); - } finally { - if (visibility == null) { - CompilerDirectives.transferToInterpreter(); - visibility = insert(SetVisibilityNode.create()); - } - visibility.execute(frame, true); - } - } - - @Override - public void setSourceSection(SourceSection source) { - // nothing to do - } - - @Override - public String getIdentifier() { - return (String) read.getIdentifier(); - } - - @Override - public boolean isFunctionLookup() { - return false; - } - - @Override - public SourceSection getLazySourceSection() { - return null; - } -} - @NodeChild(value = "delegate", type = RNode.class) abstract class ClassCheckNode extends RNode { 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 0fe9a5554b4700a1b893514c8b1549a973a4617f..65d1b59e0df489fcf2cb9a8f5729d3c313c16c20 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 @@ -82631,6 +82631,46 @@ Error: attempt to use zero-length variable name #{ `` <- 123 } Error: attempt to use zero-length variable name +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <- i); proto }; f() +[1] 1 +[1] 2 +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <<- i); proto }; f() +[1] 1 +[1] 2 +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <- i; proto }; f() +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <<- i; proto }; f() +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <- i); proto }; f() +[1] 1 +[1] 2 +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <<- i); proto }; f() +[1] 1 +[1] 2 +[1] 4 5 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <- i; proto }; f() +[1] 1 2 + +##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# +#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <<- i; proto }; f() +[1] 4 5 + ##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc# #{ `f<-` <- function(x, y=42, value) { x[1]<-value+y; x }; y<-1:10; f(y)<-7; y } [1] 49 2 3 4 5 6 7 8 9 10 @@ -131621,7 +131661,7 @@ NULL [external object] [1] 1 2 3 -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#Ignored.ImplementationError# #if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) } NULL @@ -131645,7 +131685,7 @@ NULL #if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); t <- .fastr.interop.new(tc); sort(names(t)) } [1] "field" "method" "staticField" "staticMethod" -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#Ignored.ImplementationError# #if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassMap'); to <- .fastr.interop.new(tc); sort(names(to$m())) } [1] "one" "two" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java index fe48ffd5e21ce2303ac0682f1f4ea44c84b4f40c..b775649fd5aacf44a8ecb210ab33419fe40e2bee 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -111,5 +111,14 @@ public class TestSimpleAssignment extends TestBase { assertEval("{ f <- function() { if (FALSE) { x <- 1 } ; g <- function() { x } ; g() } ; f() }"); assertEval("{ f <- function() { if (FALSE) { c <- 1 } ; g <- function() { c } ; g() } ; typeof(f()) }"); assertEval("{ `f<-` <- function(x, y=42, value) { x[1]<-value+y; x }; y<-1:10; f(y)<-7; y }"); + + assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <- i; proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <- i); proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <- i; proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <- i); proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <<- i; proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <<- i); proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <<- i; proto }; f()"); + assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <<- i); proto }; f()"); } }