diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index a3211b25f002f996ba8a590a1eb0d774a3d48d18..f5c37b9d496285ae269cdf0078e4ac883bd67ff2 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -365,7 +365,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { newNames[i] = names.getDataAt(j); } // copying is already handled by RShareable - rl.setRep(RCallNode.createCall(RSyntaxNode.INTERNAL, ((RCallNode) node).getFunctionNode(), ArgumentsSignature.get(newNames), args.getArguments())); + rl.setRep(RCallNode.createCall(RSyntaxNode.INTERNAL, ((RCallNode) node).getFunction(), ArgumentsSignature.get(newNames), args.getArguments())); } else { throw RInternalError.shouldNotReachHere(); } @@ -420,21 +420,21 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { while (call.isPromise()) { call = call.getParent(); } - RSyntaxNode syntaxNode = call.getSyntaxNode(); - return RDataFactory.createLanguage(syntaxNode.asRNode()); + RSyntaxElement syntaxNode = call.getSyntaxNode(); + return RDataFactory.createLanguage(((RSyntaxNode) syntaxNode).asRNode()); } private static RBaseNode checkBuiltin(RBaseNode bn) { if (bn instanceof RBuiltinNode) { - RSyntaxNode sn = ((RBuiltinNode) bn).getOriginalCall(); - if (sn == null) { + RSyntaxElement se = ((RBuiltinNode) bn).getOriginalCall(); + if (se == null) { /* * TODO Ideally this never happens but do.call creates trees that make finding the * original call impossible. */ return null; } else { - return (RBaseNode) sn; + return (RBaseNode) se; } } else { return bn; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java index 5bb77e6214b8099938d01efdafee8e4a6b594697..8b150e7d17bcadedeeb9fdb21a9e50e1affe1e7d 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java @@ -58,6 +58,7 @@ import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.instrument.InstrumentationState; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** @@ -152,7 +153,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa } } - private static String getPath(RSyntaxNode node) { + private static String getPath(RSyntaxElement node) { Source source = node.getSourceSection().getSource(); String path = RSource.getPath(source); return path; @@ -187,7 +188,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa * collects the stack of functions. */ private final class StatementListener implements ExecutionEventListener { - private ArrayList<ArrayList<RSyntaxNode>> intervalStacks = new ArrayList<>(); + private ArrayList<ArrayList<RSyntaxElement>> intervalStacks = new ArrayList<>(); private ArrayList<RprofState.MemoryQuad> intervalMemory = new ArrayList<>(); private volatile boolean newInterval; @@ -206,8 +207,8 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa public void onEnter(EventContext context, VirtualFrame frame) { if (newInterval) { /* context tells here we are now, frame provides callers. */ - final ArrayList<RSyntaxNode> stack = new ArrayList<>(); - stack.add((RSyntaxNode) context.getInstrumentedNode()); + final ArrayList<RSyntaxElement> stack = new ArrayList<>(); + stack.add((RSyntaxElement) context.getInstrumentedNode()); collectStack(stack); intervalStacks.add(stack); RprofState profState = RprofState.get(); @@ -220,7 +221,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa } @TruffleBoundary - private void collectStack(final ArrayList<RSyntaxNode> stack) { + private void collectStack(final ArrayList<RSyntaxElement> stack) { Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { @Override @@ -230,7 +231,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa while (call.isPromise()) { call = call.getParent(); } - RSyntaxNode syntaxNode = call.getSyntaxNode(); + RSyntaxElement syntaxNode = call.getSyntaxNode(); stack.add(syntaxNode); } return null; @@ -317,8 +318,8 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa // scan stacks to find files fileMap = new HashMap<>(); int fileIndex = 0; - for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { - for (RSyntaxNode node : intervalStack) { + for (ArrayList<RSyntaxElement> intervalStack : statementListener.intervalStacks) { + for (RSyntaxElement node : intervalStack) { String path = getPath(node); if (path != null && fileMap.get(path) == null) { fileMap.put(path, ++fileIndex); @@ -328,13 +329,13 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa } } int index = 0; - for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { + for (ArrayList<RSyntaxElement> intervalStack : statementListener.intervalStacks) { if (this.memoryProfiling) { RprofState.MemoryQuad mq = statementListener.intervalMemory.get(index); out.printf(":%d:%d:%d:%d:", mq.largeV, mq.smallV, mq.nodes, mq.copied); } - for (RSyntaxNode node : intervalStack) { - RootNode rootNode = node.asRNode().getRootNode(); + for (RSyntaxElement node : intervalStack) { + RootNode rootNode = ((RSyntaxNode) node).asRNode().getRootNode(); if (rootNode instanceof FunctionDefinitionNode) { String name = rootNode.getName(); if (this.lineProfiling) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java index 932b06f368fd4e81dd7afcadafe45fce41c5bf26..f53488c08b4fc3a18344afe792544302487d5ed8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java @@ -41,13 +41,11 @@ public abstract class CRC64 extends RBuiltinNode { @Override protected void createCasts(CastBuilder casts) { - casts.arg("x").conf(x -> x.mustNotBeMissing(RError.SHOW_CALLER2, Message.ARGUMENTS_PASSED_INTERNAL_0_1, getRBuiltin().name())).mustNotBeNull(RError.NO_CALLER, - Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.NO_CALLER, Message.INPUT_MUST_BE_STRING); + casts.arg("x").mustNotBeNull(RError.NO_CALLER, Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.NO_CALLER, Message.INPUT_MUST_BE_STRING); } @Specialization protected RAbstractStringVector crc64(RAbstractStringVector x) { return RDataFactory.createStringVector(Crc64.crc(x)); } - } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java index ad202b972214cd5b500b37986073d7e08fe209d1..a25872ef517840128479cdda2e2a640b2b183c2c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java @@ -347,7 +347,7 @@ public class FrameFunctions { sig = ArgumentsSignature.get(names.toArray(new String[names.size()])); RSyntaxNode[] newArgs = nodes.toArray(new RSyntaxNode[nodes.size()]); - RSyntaxNode modCallNode = RASTUtils.createCall(callNode.getFunctionNode(), false, sig, newArgs); + RSyntaxNode modCallNode = RASTUtils.createCall(callNode.getFunction(), false, sig, newArgs); return RDataFactory.createLanguage(modCallNode.asRNode()); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java index c77b2e404f7fe46f7c3dd1f9d1deb1d6e8d0369c..4a50c81280e7b7eed1a0050dcecf1a5a3eb06acb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java @@ -22,116 +22,24 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.api.nodes.NodeCost.NONE; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; -import com.oracle.truffle.r.nodes.RASTUtils; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode; -import com.oracle.truffle.r.runtime.nodes.RNode; /** - * The {@code .Internal} builtin. In {@code .Internal(func(args))} we have an AST where the - * RCallNode.Uninitialized and the function child should be a {@link ReadVariableNode} node with - * symbol {@code func}. We want to rewrite the AST as if the {@code func} had been called directly. - * However, we must do this in a non-destructive way otherwise deparsing and serialization will - * fail. - * - * A note on {@link RInstrumentableNode}. Since both the {@code .Internal} and the argument are - * {@link RCallNode}s both may have been wrapped. The call to {@link RASTUtils#unwrap} will go - * through any {@code RNodeWrapper} and the rewrite will remove one level of wrapping. However the - * parent of the the {@code .Internal}, which will be an {@code RNodeWrapper}, will remain so any - * instrumentation at that level will remain in place. + * .Internal is resolved during AST creation, so this builtin is only a dummy to make the name + * visible. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -@NodeInfo(cost = NONE) @RBuiltin(name = ".Internal", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"call"}, nonEvalArgs = 0, behavior = COMPLEX) public abstract class Internal extends RBuiltinNode { - private final BranchProfile errorProfile = BranchProfile.create(); - - @Child private RNode builtinCallNode; - @Specialization - protected Object doInternal(@SuppressWarnings("unused") RMissing x) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name()); + protected Object doInternal(@SuppressWarnings("unused") Object x) { + throw RInternalError.unimplemented(); } - - @Specialization - protected Object doInternal(VirtualFrame frame, RPromise x) { - if (builtinCallNode == null) { - RNode call = (RNode) x.getRep(); - RNode operand = (RNode) RASTUtils.unwrap(call); - - if (!(operand instanceof RCallNode)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_INTERNAL); - } - - RCallNode callNode = (RCallNode) operand; - RNode func = callNode.getFunctionNode(); - String name = ((ReadVariableNode) func).getIdentifier(); - RFunction function = RContext.lookupBuiltin(name); - if (function == null || function.isBuiltin() && function.getRBuiltin().getKind() != RBuiltinKind.INTERNAL) { - errorProfile.enter(); - if (function == null && notImplemented(name)) { - throw RInternalError.unimplemented(".Internal " + name); - } - throw RError.error(this, RError.Message.NO_SUCH_INTERNAL, name); - } - - // .Internal function is validated - CompilerDirectives.transferToInterpreterAndInvalidate(); - builtinCallNode = insert(RCallNode.createInternalCall(callNode, function)); - } - return builtinCallNode.execute(frame); - } - - private static boolean notImplemented(String name) { - for (String internal : NOT_IMPLEMENTED) { - if (internal.equals(name)) { - return true; - } - } - return false; - } - - // TODO check this; it is out of date - private static final String[] NOT_IMPLEMENTED = new String[]{ - ".addTryHandlers", "interruptsSuspended", "restart", "backsolve", "max.col", "row", "all.names", "comment", "`comment<-`", "list2env", "tcrossprod", "lbeta", - "beta", "lchoose", "choose", "dchisq", "pchisq", "qchisq", "dexp", "pexp", "qexp", "dgeom", "pgeom", "qgeom", "dpois", "ppois", "qpois", "dt", "pt", "qt", "dsignrank", - "psignrank", "qsignrank", "besselJ", "besselY", "psigamma", "dbeta", "pbeta", "qbeta", "dbinom", "pbinom", "qbinom", "dcauchy", "pcauchy", "qcauchy", "df", "pf", "qf", "dgamma", - "pgamma", "qgamma", "dlnorm", "plnorm", "qlnorm", "dlogis", "plogis", "qlogis", "dnbinom", "pnbinom", "qnbinom", "dnorm", "pnorm", "qnorm", "dunif", "punif", "qunif", "dweibull", - "pweibull", "qweibull", "dnchisq", "pnchisq", "qnchisq", "dnt", "pnt", "qnt", "dwilcox", "pwilcox", "qwilcox", "besselI", "besselK", "dnbinom_mu", "pnbinom_mu", "qnbinom_mu", - "dhyper", "phyper", "qhyper", "dnbeta", "pnbeta", "qnbeta", "dnf", "pnf", "qnf", "dtukey", "ptukey", "qtukey", "rchisq", "rexp", "rgeom", "rpois", "rt", "rsignrank", "rbeta", - "rbinom", "rcauchy", "rf", "rgamma", "rlnorm", "rlogis", "rnbinom", "rnbinom_mu", "rnchisq", "rnorm", "runif", "rweibull", "rwilcox", "rhyper", "sample2", "format.info", - "grepRaw", "regexec", "adist", "aregexec", "chartr", "intToBits", "rawToBits", "packBits", "intToUtf8", "strtrim", "eapply", "machine", "save", - "saveToConn", "dput", "dump", "prmatrix", "gcinfo", "gctorture", "gctorture2", "memory.profile", "recordGraphics", "sys.calls", "sys.on.exit", "rank", "builtins", "bodyCode", - "rapply", "islistfactor", "inspect", "mem.limits", "merge", "capabilitiesX11", "Cstack_info", "file.show", "file.choose", "polyroot", "mkCode", "bcClose", "is.builtin.internal", - "disassemble", "bcVersion", "load.from.file", "save.to.file", "growconst", "putconst", "getconst", "enableJIT", "setNumMathThreads", "setMaxNumMathThreads", "isatty", - "isIncomplete", "pipe", "fifo", "bzfile", "xzfile", "unz", "truncate", "rawConnection", "rawConnectionValue", "sockSelect", "gzcon", "memCompress", "memDecompress", "mkUnbound", - "env.profile", "setTimeLimit", "setSessionTimeLimit", "icuSetCollate", "lazyLoadDBflush", "findInterval", "pretty", "crc64", "rowsum_matrix", "rowsum_df", "setS4Object", - "traceOnOff", "La_qr_cmplx", "La_rs_cmplx", "La_rg_cmplx", "La_rs", "La_rs_cmplx", "La_dlange", "La_dgecon", "La_dtrcon", "La_zgecon", "La_ztrcon", "La_solve_cmplx", - "La_chol2inv", "qr_qy_real", "qr_coef_cmplx", "qr_qy_cmpl", "La_svd", "La_svd_cmplx"}; - } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java index e16383358909389c8e6b79aeecaebae583fc0358..0b7624082455fb742d7d5aba3718958da56b3113 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java @@ -77,9 +77,9 @@ public class ContextSystemFunctionFactory extends SystemFunctionFactory { } @Specialization - protected Object systemFunction(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern) { + protected Object systemFunction(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { initContextRscriptNode(); - Object result = contextRscriptNode.executeBuiltin(frame, args, env, intern); + Object result = contextRscriptNode.execute(args, env, intern); return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index dd68c15f3a66753ccf27bed53273331db337bcf7..aa78158d736e78f0f48b1a16f99e900caaf71ee0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -22,7 +22,13 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; @@ -256,6 +262,9 @@ public class FastRContext { @RBuiltin(name = ".fastr.context.rscript", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX) public abstract static class Rscript extends RBuiltinNode { + + public abstract Object execute(RAbstractStringVector args, RAbstractStringVector env, boolean intern); + @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE}; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java index 8a1e544b5231732db03711ea6fa77808327c80a9..271946acb29ae950b84d53faa0b7736c23e048e8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java @@ -33,6 +33,7 @@ import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.InternalNode; import com.oracle.truffle.r.nodes.control.BlockNode; import com.oracle.truffle.r.nodes.control.BreakNode; import com.oracle.truffle.r.nodes.control.ForNode; @@ -139,6 +140,8 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { return new BlockNode(source, lhsLookup, args.stream().map(n -> n.value.asRNode()).toArray(RNode[]::new)); case "missing": return new MissingNode(source, lhsLookup, createSignature(args), args.stream().map(a -> a.value).toArray(RSyntaxElement[]::new)); + case ".Internal": + return InternalNode.create(source, lhsLookup, createSignature(args), args.stream().map(a -> a.value).toArray(RSyntaxNode[]::new)); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java index 110a168f5d2460dc4e56ec5c8537ff20118363a6..21a4e1293a6cecd42faaa778194bc48c1d43944a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java @@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -96,7 +97,7 @@ public class RASTUtils { } @TruffleBoundary - public static RSyntaxNode getOriginalCall(Node node) { + public static RSyntaxElement getOriginalCall(Node node) { Node p = node.getParent(); while (p != null) { if (p instanceof RBuiltinNode) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java new file mode 100644 index 0000000000000000000000000000000000000000..48ff3250322af8cda13932b504247456e30646be --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java @@ -0,0 +1,346 @@ +/* + * 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 + * 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.builtin; + +import java.util.Arrays; +import java.util.List; + +import com.oracle.truffle.api.CompilerDirectives; +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.control.OperatorNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; +import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.REmpty; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; + +/** + * This node is used during AST creation to represent a .Internal call. Upon the first execution, it + * will examine its arguments, raising errors if necessary, and rewrite itself to a version that + * fits the arguments. The main difference in how arguments are passed is in whether varargs are + * introduced or forwarded by the call to the .Internal. + */ +public abstract class InternalNode extends OperatorNode { + + protected final ArgumentsSignature outerSignature; + protected final RSyntaxNode[] outerArgs; + + public InternalNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs) { + super(src, operator); + this.outerSignature = outerSignature; + this.outerArgs = outerArgs; + } + + public static InternalNode create(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs) { + return new InternalUninitializedNode(src, operator, outerSignature, outerArgs); + } + + /** + * Represents an uninitialized .Internal call, executing will replace it with a more specific + * implementation. + */ + private static final class InternalUninitializedNode extends InternalNode { + + InternalUninitializedNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs) { + super(src, operator, outerSignature, outerArgs); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (outerArgs.length != 1) { + throw RError.error(RError.SHOW_CALLER, Message.ARGUMENTS_PASSED, outerArgs.length, ".Internal", 1); + } + if (!(outerArgs[0] instanceof RSyntaxCall)) { + throw RError.error(RError.SHOW_CALLER, Message.INVALID_ARG, ".Internal()"); + } + + RSyntaxCall call = (RSyntaxCall) outerArgs[0]; + RSyntaxElement lhs = call.getSyntaxLHS(); + + // extract the builtin name + String name = null; + if (lhs instanceof RSyntaxLookup) { + name = ((RSyntaxLookup) lhs).getIdentifier(); + } else if (lhs instanceof RSyntaxConstant) { + Object constant = ((RSyntaxConstant) lhs).getValue(); + if (constant instanceof String) { + name = (String) constant; + } else if (constant instanceof RAbstractStringVector) { + RAbstractStringVector stringVector = (RAbstractStringVector) constant; + if (stringVector.getLength() == 1) { + name = stringVector.getDataAt(0); + } + } + } + if (name == null) { + throw RError.error(RError.SHOW_CALLER, Message.INVALID_ARG, ".Internal()"); + } + + RFunction function = RContext.lookupBuiltin(name); + if (function == null || function.isBuiltin() && function.getRBuiltin().getKind() != RBuiltinKind.INTERNAL) { + // determine whether we're supposed to implement this builtin + if (function == null && NOT_IMPLEMENTED.contains(name)) { + throw RInternalError.unimplemented(".Internal " + name); + } + throw RError.error(RError.SHOW_CALLER, RError.Message.NO_SUCH_INTERNAL, name); + } + + RBuiltinFactory factory = (RBuiltinFactory) function.getRBuiltin(); + RSyntaxElement[] callArgs = call.getSyntaxArguments(); + + // verify the number of arguments + if (factory.getSignature().getVarArgCount() == 0) { + if (callArgs.length != factory.getSignature().getLength()) { + throw RError.error(RError.SHOW_CALLER, Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", factory.getSignature().getLength()); + } + for (int i = 0; i < callArgs.length; i++) { + if (callArgs[i] instanceof RSyntaxConstant && ((RSyntaxConstant) callArgs[i]).getValue() == REmpty.instance) { + throw RError.error(RError.SHOW_CALLER, Message.ARGUMENT_EMPTY, i + 1); + } + } + } + // look for "..." argument and verify that only one "..." is given (FastR restriction) + int varArgForward = ArgumentsSignature.NO_VARARG; + for (int i = 0; i < callArgs.length; i++) { + RSyntaxElement arg = callArgs[i]; + if (arg instanceof RSyntaxLookup && ((RSyntaxLookup) arg).getIdentifier().equals(ArgumentsSignature.VARARG_NAME)) { + RInternalError.guarantee(varArgForward == ArgumentsSignature.NO_VARARG, "more than one '...' in .Internal arguments is not supported"); + varArgForward = i; + } + } + int varArgIndex = factory.getSignature().getVarArgIndex(); + if (varArgForward == varArgIndex) { + if (varArgIndex == ArgumentsSignature.NO_VARARG) { + return replace(new InternalCallDefaultNode(getLazySourceSection(), operator, outerSignature, outerArgs, factory, callArgs)).execute(frame); + } else { + return replace(new InternalCallVarArgForwardNode(getLazySourceSection(), operator, outerSignature, outerArgs, factory, callArgs)).execute(frame); + } + } else if (varArgForward == ArgumentsSignature.NO_VARARG) { + return replace(new InternalCallWrapNode(getLazySourceSection(), operator, outerSignature, outerArgs, factory, callArgs)).execute(frame); + } else { + /* + * So far, refusing to handle .Internal calls that require complex argument + * rematching seems reasonable. + */ + throw RInternalError.shouldNotReachHere("complex argument matching in .Internal"); + } + } + } + + /** + * Base class for all actual implementations of .Internal, handles everything but preparing the + * argument array. + */ + private abstract static class InternalCallNode extends InternalNode { + + protected final RBuiltinFactory factory; + protected final int varArgIndex; + + @Children protected final RNode[] arguments; + @Children protected final CastNode[] casts; + @Child private RBuiltinNode builtin; + @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + + InternalCallNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs, RBuiltinFactory factory, RSyntaxElement[] args) { + super(src, operator, outerSignature, outerArgs); + this.factory = factory; + this.builtin = factory.getConstructor().get(); + this.casts = builtin.getCasts(); + this.arguments = new RNode[args.length]; + for (int i = 0; i < args.length; i++) { + arguments[i] = ((RSyntaxNode) args[i]).asRNode(); + } + this.varArgIndex = factory.getSignature().getVarArgIndex(); + if (varArgIndex != ArgumentsSignature.NO_VARARG) { + assert casts.length <= varArgIndex || casts[varArgIndex] == null : "no casts on '...' arguments to .Internals"; + } + } + + protected abstract Object[] prepareArgs(VirtualFrame frame); + + @Override + public Object execute(VirtualFrame frame) { + Object result = builtin.executeBuiltin(frame, prepareArgs(frame)); + assert result != null : "builtins cannot return 'null': " + factory.getName(); + assert !(result instanceof RConnection) : "builtins cannot return connection': " + factory.getName(); + visibility.execute(frame, factory.getVisibility()); + return result; + } + + @Override + public void voidExecute(VirtualFrame frame) { + builtin.executeBuiltin(frame, prepareArgs(frame)); + } + } + + /** + * Handling the case where there are no varargs. + */ + private static final class InternalCallDefaultNode extends InternalCallNode { + + InternalCallDefaultNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs, RBuiltinFactory factory, RSyntaxElement[] args) { + super(src, operator, outerSignature, outerArgs, factory, args); + assert args.length == factory.getSignature().getLength(); + } + + @Override + @ExplodeLoop + protected Object[] prepareArgs(VirtualFrame frame) { + Object[] args = new Object[arguments.length]; + for (int i = 0; i < args.length; i++) { + Object value = arguments[i].execute(frame); + if (i < casts.length && casts[i] != null) { + value = casts[i].execute(value); + } + args[i] = value; + } + return args; + } + } + + /** + * Handling the case where there is a single vararg parameter that is forwarded to the builtin. + * Any promises in the vararg need to be forced. + */ + private static final class InternalCallVarArgForwardNode extends InternalCallNode { + + @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode(); + + InternalCallVarArgForwardNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs, RBuiltinFactory factory, RSyntaxElement[] args) { + super(src, operator, outerSignature, outerArgs, factory, args); + assert args.length == factory.getSignature().getLength(); + } + + @Override + @ExplodeLoop + protected Object[] prepareArgs(VirtualFrame frame) { + Object[] args = new Object[arguments.length]; + for (int i = 0; i < args.length; i++) { + Object value = arguments[i].execute(frame); + if (i == varArgIndex) { + value = forcePromises(frame, (RArgsValuesAndNames) value); + } else { + if (i < casts.length && casts[i] != null) { + value = casts[i].execute(value); + } + } + args[i] = value; + } + return args; + } + + private RArgsValuesAndNames forcePromises(VirtualFrame frame, RArgsValuesAndNames varArgs) { + Object[] array = new Object[varArgs.getLength()]; + for (int i = 0; i < array.length; i++) { + array[i] = promiseHelper.checkEvaluate(frame, varArgs.getArgument(i)); + } + return new RArgsValuesAndNames(array, varArgs.getSignature()); + } + } + + /** + * Handles the case where the .Internal call specifies multiple arguments that need to be + * wrapped in a vararg. + */ + private static final class InternalCallWrapNode extends InternalCallNode { + + InternalCallWrapNode(SourceSection src, RSyntaxLookup operator, ArgumentsSignature outerSignature, RSyntaxNode[] outerArgs, RBuiltinFactory factory, RSyntaxElement[] args) { + super(src, operator, outerSignature, outerArgs, factory, args); + } + + @Override + @ExplodeLoop + protected Object[] prepareArgs(VirtualFrame frame) { + Object[] args = new Object[factory.getSignature().getLength()]; + + for (int i = 0; i < args.length - 1; i++) { + Object value = arguments[i].execute(frame); + if (i < casts.length && casts[i] != null) { + value = casts[i].execute(value); + } + args[i] = value; + } + Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)]; + for (int i = 0; i < varArgs.length; i++) { + varArgs[i] = arguments[args.length - 1 + i].execute(frame); + } + args[args.length - 1] = new RArgsValuesAndNames(varArgs, ArgumentsSignature.empty(varArgs.length)); + return args; + } + } + + @Override + public RSyntaxNode[] getSyntaxArguments() { + return outerArgs; + } + + @Override + public ArgumentsSignature getSyntaxSignature() { + return outerSignature; + } + + /* + * This is a list of .Internal functions that should be available but may not be implemented + * yet. When an unknown .Internal is encountered, this list is queried to see whether it's a + * non-existing or an unimplemented builtin. For builtins that are implemented, it makes no + * difference if they are in the list or not. + * + * Some builtins, e.g., the distribution functions, are in this list because GNUR lists them as + * .Internal although they are never used in this way. Therefore, this list is not an accurate + * listing of missing builtins. + */ + private static final List<String> NOT_IMPLEMENTED = Arrays.asList( + ".addTryHandlers", "interruptsSuspended", "restart", "backsolve", "max.col", "comment", "`comment<-`", "list2env", "tcrossprod", + "lbeta", "beta", "lchoose", "dchisq", "pchisq", "qchisq", "dexp", "pexp", "qexp", "dgeom", "pgeom", "qgeom", "dpois", "ppois", "qpois", "dt", "pt", "qt", "dsignrank", "psignrank", + "qsignrank", "besselJ", "besselY", "psigamma", "dbeta", "pbeta", "qbeta", "dbinom", "pbinom", "qbinom", "dcauchy", "pcauchy", "qcauchy", "df", "pf", "qf", "dgamma", "pgamma", + "qgamma", "dlnorm", "plnorm", "qlnorm", "dlogis", "plogis", "qlogis", "dnbinom", "pnbinom", "qnbinom", "dnorm", "pnorm", "qnorm", "dunif", "punif", "qunif", "dweibull", "pweibull", + "qweibull", "dnchisq", "pnchisq", "qnchisq", "dnt", "pnt", "qnt", "dwilcox", "pwilcox", "qwilcox", "besselI", "besselK", "dnbinom_mu", "pnbinom_mu", "qnbinom_mu", "dhyper", + "phyper", "qhyper", "dnbeta", "pnbeta", "qnbeta", "dnf", "pnf", "qnf", "dtukey", "ptukey", "qtukey", "rchisq", "rexp", "rgeom", "rpois", "rt", "rsignrank", "rbeta", "rbinom", + "rcauchy", "rf", "rgamma", "rlnorm", "rlogis", "rnbinom", "rnbinom_mu", "rnchisq", "rnorm", "runif", "rweibull", "rwilcox", "rhyper", + "format.info", "grepRaw", "regexec", "adist", "aregexec", "chartr", "packBits", "strtrim", "eapply", "machine", "save", "dump", "prmatrix", "gcinfo", "gctorture", "gctorture2", + "memory.profile", "recordGraphics", "sys.on.exit", "builtins", "bodyCode", "rapply", "inspect", + "mem.limits", "capabilitiesX11", "Cstack_info", "file.choose", "polyroot", "mkCode", "bcClose", "is.builtin.internal", "disassemble", "bcVersion", "load.from.file", "save.to.file", + "growconst", "putconst", "getconst", "setNumMathThreads", "setMaxNumMathThreads", "isatty", "isIncomplete", "pipe", "fifo", "unz", "truncate", "rawConnection", + "rawConnectionValue", "sockSelect", "gzcon", "memCompress", "memDecompress", "mkUnbound", "env.profile", "setSessionTimeLimit", "icuSetCollate", "findInterval", "rowsum_df", + "La_qr_cmplx", "La_rs_cmplx", "La_rg_cmplx", "La_rs_cmplx", "La_dlange", "La_dgecon", "La_dtrcon", "La_zgecon", "La_ztrcon", "La_solve_cmplx", "La_chol2inv", "qr_qy_real", + "qr_coef_cmplx", "qr_qy_cmpl", "La_svd", "La_svd_cmplx"); +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java index 46e7f64a39a1f501cf2a7e2e74527e7c3e8e7948..e5ae547f462f1e4142267a508b646c9e3f61704d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java @@ -42,7 +42,9 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; @TypeSystemReference(RTypes.class) public abstract class RBuiltinNode extends RBaseNode { @@ -74,7 +76,10 @@ public abstract class RBuiltinNode extends RBaseNode { RBuiltinNode node = builtin.getConstructor().get(); FormalArguments formals = FormalArguments.createForBuiltin(node.getDefaultParameterValues(), builtin.getSignature()); - assert builtin.getKind() != RBuiltinKind.INTERNAL || node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values"; + if (builtin.getKind() == RBuiltinKind.INTERNAL) { + assert node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values"; + assert builtin.getSignature().getVarArgCount() == 0 || builtin.getSignature().getVarArgIndex() == builtin.getSignature().getLength() - 1 : "only last argument can be vararg"; + } FrameDescriptor frameDescriptor = new FrameDescriptor(); RBuiltinRootNode root = new RBuiltinRootNode(builtin, node, formals, frameDescriptor, null); @@ -107,12 +112,21 @@ public abstract class RBuiltinNode extends RBaseNode { * {@code do.call("func", )} have a {@link RBuiltinRootNode} as a parent, which carries no * context about the original call, so we return {@code null}. */ - public RSyntaxNode getOriginalCall() { + public RSyntaxElement getOriginalCall() { Node p = getParent(); - if (p instanceof RBuiltinRootNode) { - return null; - } else { - return ((RBaseNode) getParent()).asRSyntaxNode(); + while (true) { + if (p == null) { + return null; + } + if (p instanceof RSyntaxCall) { + RSyntaxCall call = (RSyntaxCall) p; + if (call.getSyntaxArguments().length > 0 && call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier().equals(".Internal")) { + // unwrap .Internal calls + return call.getSyntaxArguments()[0]; + } + return call; + } + p = p.getParent(); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java index e034cfa67da52aab6d8a18ab88da0b95344e6a95..b137ce93957a49ff12bbb77f5edd43164f3ef873 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; public abstract class CallMatcherNode extends RBaseNode { @@ -238,7 +238,7 @@ public abstract class CallMatcherNode extends RBaseNode { if (call != null) { RCaller parent = RArguments.getCall(frame).getParent(); String genFunctionName = functionName == null ? function.getName() : functionName; - Supplier<RSyntaxNode> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, preparePermutation, suppliedArguments, suppliedSignature); + Supplier<RSyntaxElement> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, preparePermutation, suppliedArguments, suppliedSignature); RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) : RCaller.create(frame, parent, argsSupplier); try { return call.execute(frame, cachedFunction, caller, null, reorderedArgs, matchedArgs.getSignature(), cachedFunction.getEnclosingFrame(), dispatchArgs); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java index e2019c4c78506fca390f3b711385e08ee8b1d999..85c1172c4eaf3b0f99c93907ff20423516864768 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java @@ -72,9 +72,13 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode, RSyntaxFunction { @@ -184,41 +188,49 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo } private boolean needsAnyBuiltinSplitting() { - NodeCountFilter findAlwaysSplitInternal = node -> { - if (node instanceof RCallNode) { - RCallNode internalCall = (RCallNode) node; - - if (internalCall.getFunctionNode() instanceof ReadVariableNode) { - ReadVariableNode readInternal = (ReadVariableNode) internalCall.getFunctionNode(); - + RSyntaxVisitor<Boolean> visitor = new RSyntaxVisitor<Boolean>() { + + @Override + protected Boolean visit(RSyntaxCall element) { + RSyntaxElement lhs = element.getSyntaxLHS(); + RSyntaxElement[] arguments = element.getSyntaxArguments(); + if (lhs instanceof RSyntaxLookup) { + String function = ((RSyntaxLookup) lhs).getIdentifier(); /* * TODO This is a hack to make sapply split lapply. We need to find better ways * to do this. If a function uses lapply anywhere as name then it gets split. * This could get exploited. */ - RBuiltinDescriptor directBuiltin = RContext.lookupBuiltinDescriptor(readInternal.getIdentifier()); + RBuiltinDescriptor directBuiltin = RContext.lookupBuiltinDescriptor(function); if (directBuiltin != null && directBuiltin.isSplitCaller()) { return true; } - if (readInternal.getIdentifier().equals(".Internal")) { - Node internalFunctionArgument = RASTUtils.unwrap(internalCall.getArguments().getArguments()[0]); - if (internalFunctionArgument instanceof RCallNode) { - RCallNode innerCall = (RCallNode) internalFunctionArgument; - if (innerCall.getFunctionNode() instanceof ReadVariableNode) { - ReadVariableNode readInnerCall = (ReadVariableNode) innerCall.getFunctionNode(); - RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(readInnerCall.getIdentifier()); - if (builtin != null && builtin.isSplitCaller()) { - return true; - } - } - } + } + for (RSyntaxElement arg : arguments) { + if (arg != null && accept(arg)) { + return true; } } + return false; + } + + @Override + protected Boolean visit(RSyntaxConstant element) { + return false; + } + + @Override + protected Boolean visit(RSyntaxLookup element) { + return false; + } + + @Override + protected Boolean visit(RSyntaxFunction element) { + return false; } - return false; }; - return NodeUtil.countNodes(this, findAlwaysSplitInternal) > 0; + return visitor.accept(getSyntaxBody()); } @Override @@ -258,6 +270,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo throw e; } catch (RError e) { CompilerDirectives.transferToInterpreter(); + SetVisibilityNode.executeSlowPath(frame, false); throw e; } catch (DebugExitException | JumpToTopLevelException | ExitException | ThreadDeath e) { /* diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java index 003cbce289049f7d09f3f347ddee6f2b5ad00062..ca010cb5525591933fbb4e5edf5512401033cdf7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java @@ -22,47 +22,13 @@ */ package com.oracle.truffle.r.nodes.function; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.Instrumentable; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode; import com.oracle.truffle.r.runtime.nodes.RNode; -final class ForcePromiseNode extends RNode { - - @Child private RNode valueNode; - @Child private PromiseHelperNode promiseHelper; - private final BranchProfile nonPromiseProfile = BranchProfile.create(); - - ForcePromiseNode(RNode valueNode) { - this.valueNode = valueNode; - } - - public RNode getValueNode() { - - return valueNode; - } - - @Override - public Object execute(VirtualFrame frame) { - Object value = valueNode.execute(frame); - if (value instanceof RPromise) { - if (promiseHelper == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseHelperNode()); - } - return promiseHelper.evaluate(frame, (RPromise) value); - } else { - nonPromiseProfile.enter(); - return value; - } - } -} - @TypeSystemReference(RTypes.class) @Instrumentable(factory = com.oracle.truffle.r.nodes.function.RCallBaseNodeWrapperFactory.class) public abstract class RCallBaseNode extends RNode implements RInstrumentableNode { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 426f67c5df151dbaff46664de337831a1fc623b3..d2e30dd9e8bdbe712eeb9a886affff2551e83603 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -89,6 +89,7 @@ import com.oracle.truffle.r.runtime.builtins.FastPathFactory; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; @@ -108,7 +109,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeInfo(cost = NodeCost.NONE) -@NodeChild(value = "function", type = ForcePromiseNode.class) +@NodeChild(value = "function", type = RNode.class) public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { // currently cannot be RSourceSectionNode because of TruffleDSL restrictions @@ -132,7 +133,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return sourceSection; } - protected abstract ForcePromiseNode getFunction(); + public abstract RNode getFunction(); private final RSyntaxNode[] arguments; private final int[] varArgIndexes; @@ -256,7 +257,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } protected RNode createDispatchArgument(int index) { - return new ForcePromiseNode(RASTUtils.cloneNode(arguments[index].asRNode())); + return RContext.getASTBuilder().process(arguments[index]).asRNode(); } /** @@ -530,15 +531,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS throw RError.error(RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION); } - public RNode getFunctionNode() { - if (getFunction() != null) { - // Only the very 1. RootCallNode on the top level contains the one-and-only function - // node - return getFunction().getValueNode(); - } - return getParentCallNode().getFunctionNode(); - } - public CallArgumentsNode createArguments(FrameSlot tempFrameSlot, boolean modeChange, boolean modeChangeAppliesToAll) { RNode[] args = new RNode[arguments.length]; for (int i = 0; i < arguments.length; i++) { @@ -615,7 +607,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS * {@code src == RSyntaxNode.EAGER_DEPARSE} we force a deparse. */ public static RCallNode createCall(SourceSection src, RNode function, ArgumentsSignature signature, RSyntaxNode... arguments) { - return RCallNodeGen.create(src, arguments, signature, new ForcePromiseNode(function)); + return RCallNodeGen.create(src, arguments, signature, function); } public static RCallNode createExplicitCall(Object explicitArgsIdentifier) { @@ -630,14 +622,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return null; } - private RCallNode getParentCallNode() { - RNode parent = (RNode) unwrapParent(); - if (!(parent instanceof RCallNode)) { - throw RInternalError.shouldNotReachHere(); - } - return (RCallNode) parent; - } - static boolean needsSplitting(RootCallTarget target) { RRootNode root = (RRootNode) target.getRootNode(); return root.containsDispatch() || root.needsSplitting(); @@ -994,8 +978,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Override public RSyntaxElement getSyntaxLHS() { - ForcePromiseNode func = getFunction(); - return func == null || func.getValueNode() == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : getFunctionNode().asRSyntaxNode(); + return getFunction() == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : getFunction().asRSyntaxNode(); } @Override 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 1a81c60bc464b40869f22733cefd740ec0181f9b..49863fcd9a3f8270f41307e31e8798d1e826fb5c 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 @@ -117,7 +117,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode return sourceSection; } - @Child private ForcePromiseNode functionNode; + @Child private RNode functionNode; @Child private RNode special; private final RSyntaxNode[] arguments; @@ -139,7 +139,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode this.sourceSection = sourceSection; this.expectedFunction = expectedFunction; this.special = special; - this.functionNode = new ForcePromiseNode(functionNode); + this.functionNode = functionNode; this.arguments = arguments; this.signature = signature; } @@ -272,7 +272,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode } private RCallNode getRCallNode(RSyntaxNode[] newArguments) { - return RCallNode.createCall(sourceSection, functionNode == null ? null : functionNode.getValueNode(), signature, newArguments); + return RCallNode.createCall(sourceSection, functionNode, signature, newArguments); } private RCallNode getRCallNode() { @@ -300,8 +300,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode @Override public RSyntaxElement getSyntaxLHS() { - ForcePromiseNode func = functionNode; - return func == null || func.getValueNode() == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : func.getValueNode().asRSyntaxNode(); + return functionNode == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : functionNode.asRSyntaxNode(); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java index e1902ab85e28fbf91f66c6036849514b7c6c7ddf..8fb51170f9cad3819b28b72e310e239459cd4e99 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java @@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** @@ -54,24 +55,24 @@ public final class RCallerHelper { * @param arguments array with arguments and corresponding names. This method strips any * {@code RMissing} arguments and unrolls all varargs within the arguments array. */ - public static Supplier<RSyntaxNode> createFromArguments(RFunction function, RArgsValuesAndNames arguments) { + public static Supplier<RSyntaxElement> createFromArguments(RFunction function, RArgsValuesAndNames arguments) { return createFromArgumentsInternal(function, arguments); } /** * @see #createFromArguments(RFunction, RArgsValuesAndNames) */ - public static Supplier<RSyntaxNode> createFromArguments(String function, RArgsValuesAndNames arguments) { + public static Supplier<RSyntaxElement> createFromArguments(String function, RArgsValuesAndNames arguments) { return createFromArgumentsInternal(function, arguments); } - public static Supplier<RSyntaxNode> createFromArgumentsInternal(final Object function, final RArgsValuesAndNames arguments) { - return new Supplier<RSyntaxNode>() { + public static Supplier<RSyntaxElement> createFromArgumentsInternal(final Object function, final RArgsValuesAndNames arguments) { + return new Supplier<RSyntaxElement>() { - RSyntaxNode syntaxNode = null; + RSyntaxElement syntaxNode = null; @Override - public RSyntaxNode get() { + public RSyntaxElement get() { if (syntaxNode == null) { int length = 0; for (int i = 0; i < arguments.getLength(); i++) { @@ -122,13 +123,13 @@ public final class RCallerHelper { /** * This method calculates the signature of the permuted arguments lazily. */ - public static Supplier<RSyntaxNode> createFromArguments(String function, long[] preparePermutation, Object[] suppliedArguments, ArgumentsSignature suppliedSignature) { - return new Supplier<RSyntaxNode>() { + public static Supplier<RSyntaxElement> createFromArguments(String function, long[] preparePermutation, Object[] suppliedArguments, ArgumentsSignature suppliedSignature) { + return new Supplier<RSyntaxElement>() { - RSyntaxNode syntaxNode = null; + RSyntaxElement syntaxNode = null; @Override - public RSyntaxNode get() { + public RSyntaxElement get() { if (syntaxNode == null) { Object[] values = new Object[preparePermutation.length]; String[] names = new String[preparePermutation.length]; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java index f4bd0702a18bac1280a0613bd07463251c42fadf..e148ee23a00458c5cb45193e1de508c8128a7178 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java @@ -197,7 +197,7 @@ public final class MissingNode extends OperatorNode { if (level == null && readVarArgs == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); if (args.length != 1) { - throw RError.error(this, Message.ARGUMENTS_PASSED, args.length, "missing", 1); + throw RError.error(this, Message.ARGUMENTS_PASSED, args.length, "'missing'", 1); } RSyntaxElement arg = args[0]; if (!(arg instanceof RSyntaxLookup)) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java index e5315d7410c862e2c6038a5a747fcf663aab322c..c20ab69256fd7633f839275c9f7ebe88f9db6cbc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java @@ -114,4 +114,12 @@ public final class SetVisibilityNode extends Node { CompilerAsserts.neverPartOfCompilation(); frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), caller.getVisibility()); } + + /** + * Slow-path version of {@link #execute(Frame, boolean)}. + */ + public static void executeSlowPath(Frame frame, boolean visibility) { + CompilerAsserts.neverPartOfCompilation(); + frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), visibility); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java index 4be981a574ff0db8c4c8bfb736f99a60452b1748..298d82873a04bbefda07c6788471b543234a7c10 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_loadMethod function) @@ -121,7 +122,7 @@ abstract class LoadMethod extends RBaseNode { } else { currentFunction = (RFunction) loadMethodFind.execute(frame, methodsEnv.getFrame(methodsFrameAccessProfile)); } - RSyntaxNode originalCall = RASTUtils.getOriginalCall(this); + RSyntaxElement originalCall = RASTUtils.getOriginalCall(this); RCaller caller = originalCall == null ? RCaller.createInvalid(frame) : RCaller.create(frame, originalCall); if (cached.profile(currentFunction == loadMethodFunction)) { // TODO: technically, someone could override loadMethod function and access the diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java index 9d9834d6b5cb7aa350d0915b4ccd78d0767ab9d7..6771af91b7f7403faed55595e3efe24138cdbb9f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java @@ -25,7 +25,7 @@ package com.oracle.truffle.r.runtime; import java.util.function.Supplier; import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; /** * Represents the caller of a function and stored in {@link RArguments}. A value of this type never @@ -72,9 +72,9 @@ public final class RCaller { return parent; } - public RSyntaxNode getSyntaxNode() { + public RSyntaxElement getSyntaxNode() { assert payload != null && !(payload instanceof RCaller) : payload == null ? "null RCaller" : "promise RCaller"; - return payload instanceof RSyntaxNode ? (RSyntaxNode) payload : (RSyntaxNode) ((Supplier<?>) payload).get(); + return payload instanceof RSyntaxElement ? (RSyntaxElement) payload : (RSyntaxElement) ((Supplier<?>) payload).get(); } public boolean isValidCaller() { @@ -97,22 +97,22 @@ public final class RCaller { return new RCaller(depthFromFrame(callingFrame), parent, null); } - public static RCaller create(Frame callingFrame, RSyntaxNode node) { + public static RCaller create(Frame callingFrame, RSyntaxElement node) { assert node != null; return new RCaller(callingFrame, node); } - public static RCaller create(Frame callingFrame, RCaller parent, RSyntaxNode node) { + public static RCaller create(Frame callingFrame, RCaller parent, RSyntaxElement node) { assert node != null; return new RCaller(depthFromFrame(callingFrame), parent, node); } - public static RCaller create(Frame callingFrame, Supplier<RSyntaxNode> supplier) { + public static RCaller create(Frame callingFrame, Supplier<RSyntaxElement> supplier) { assert supplier != null; return new RCaller(callingFrame, supplier); } - public static RCaller create(Frame callingFrame, RCaller parent, Supplier<RSyntaxNode> supplier) { + public static RCaller create(Frame callingFrame, RCaller parent, Supplier<RSyntaxElement> supplier) { assert supplier != null; return new RCaller(depthFromFrame(callingFrame), parent, supplier); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 290c7a823ce0a2b59de62fd1c4aceadaf23ef3ca..2f152c4f51da159ede1efa0f1ba26154010f00d8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -572,7 +572,7 @@ public final class RError extends RuntimeException { SUBSCRIPT_TYPES("incompatible types (from %s to %s) in [[ assignment"), INCOMPATIBLE_METHODS("incompatible methods (\"%s\", \"%s\") for \"%s\""), RECURSIVE_INDEXING_FAILED("recursive indexing failed at level %d"), - ARGUMENTS_PASSED("%d arguments passed to '%s' which requires %d"), + ARGUMENTS_PASSED("%d arguments passed to %s which requires %d"), ARGUMENTS_PASSED_0_1("0 arguments passed to '%s' which requires 1"), ARGUMENTS_PASSED_INTERNAL_0_1("0 arguments passed to .Internal(%s) which requires 1"), ARGUMENT_IGNORED("argument '%s' will be ignored"), @@ -759,6 +759,7 @@ public final class RError extends RuntimeException { ATTEMPT_TO_REPLICATE_NO_VECTOR("attempt to replicate non-vector"), INCORRECT_ARG_TYPE("incorrect type for %s argument"), INVALID_ARG_OF_LENGTH("invalid %s argument of length %d"), + INVALID_ARG("invalid %s argument"), INVALID_FILENAME_PATTERN("invalid filename pattern"), INVALID_FILE_EXT("invalid file extension"), NO("no '%s'"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java index 208b455e8791b694d03b44ae28c913044c9061b3..b24242d83805613c6f717e4bf4d3ad420d401daf 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java @@ -101,7 +101,8 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> { if (builtin != null && builtin.getKind() == RBuiltinKind.INTERNAL) { ArgumentsSignature signature = builtin.getSignature(); if (signature.getVarArgCount() == 0) { - assert innerArguments.length == signature.getLength(); + // holds only for well-formed code, so we cannot rely on it: + // assert innerArguments.length == signature.getLength(); } else { assert signature.getVarArgCount() == 1 : signature; assert innerArguments.length == signature.getLength() || signature.getVarArgIndex() == signature.getLength() - 1 : signature; 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 56bce3bc119bc4027798338a14af68e23e6d0538..f8e922a309213fb0ed51df55aff111a0c07e99cb 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 @@ -33225,11 +33225,11 @@ a f g bar 4 2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar# -#{ .Internal(nchar('ff', 'chars', FALSE)) } +#{ .Internal(nchar('ff', 'chars', FALSE, FALSE)) } [1] 2 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar# -#{ .Internal(nchar(c(10,130), 'chars', FALSE)) } +#{ .Internal(nchar(c(10,130), 'chars', FALSE, FALSE)) } [1] 2 3 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNChar# diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java index 232fe1a6a324287bbc63a5b50dc842a2c459bc65..a55986b74187308bfc40b5ade993b58e108b5314 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java @@ -82,8 +82,8 @@ public class TestBuiltin_nchar extends TestBase { assertEval("{ nchar(c(\"hello\", \"hi\")) }"); assertEval("{ nchar(c(\"hello\", \"hi\", 10, 130)) }"); assertEval("{ nchar(c(10,130)) }"); - assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE)) }"); - assertEval("{ .Internal(nchar('ff', 'chars', FALSE)) }"); + assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE, FALSE)) }"); + assertEval("{ .Internal(nchar('ff', 'chars', FALSE, FALSE)) }"); assertEval("v <- c(a=1,b=1234,c='ff',d='gg'); dim(v) <- c(foo=2,bar=2); dimnames(v) <- list(a=c('foo', 'bar'), n=c('f','g')); nchar(v)"); }