From d2ea1585c2cc3210a97c32c80187d48c6358f266 Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Wed, 18 Jun 2014 14:12:34 -0700 Subject: [PATCH] refactoring to clean up project cycles --- .../r/nodes/access/ReadVariableNode.java | 2 +- .../r/nodes/builtin/RBuiltinPackage.java | 2 +- .../truffle/r/nodes/builtin/base/DoCall.java | 2 +- .../r/nodes/builtin/base/EvalFunctions.java | 8 +- .../truffle/r/nodes/builtin/base/Exists.java | 2 +- .../truffle/r/nodes/builtin/base/Parse.java | 4 +- .../nodes/builtin/base/PrettyPrinterNode.java | 3 +- .../r/nodes/builtin/base/ProcTime.java | 4 +- .../nodes/builtin/debug/DebugInfoBuiltin.java | 2 +- .../function/FunctionDefinitionNode.java | 13 +- .../src/com/oracle/truffle/r/runtime/DCF.java | 1 - .../r/runtime/RBuiltinLookupProvider.java | 27 ---- .../oracle/truffle/r/runtime/RContext.java | 123 +++++++++++++++--- .../truffle/r/runtime/REnvironment.java | 4 +- .../oracle/truffle/r/runtime/RPackages.java | 15 --- .../com/oracle/truffle/r/engine}/REngine.java | 103 +++++---------- .../com/oracle/truffle/r/shell/RCommand.java | 6 +- .../truffle/r/test/generate/FastRSession.java | 4 +- mx.fastr/projects | 2 +- 19 files changed, 166 insertions(+), 161 deletions(-) delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RBuiltinLookupProvider.java rename {com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin => com.oracle.truffle.r.shell/src/com/oracle/truffle/r/engine}/REngine.java (79%) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java index 07d76cc910..098f100eac 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java @@ -139,7 +139,7 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro } private ReadVariableNode resolveNonFrame() { - RFunction lookupResult = RContext.getLookup().lookup(RRuntime.toString(symbol)); + RFunction lookupResult = RContext.getEngine().lookupBuiltin(RRuntime.toString(symbol)); if (lookupResult != null) { return BuiltinFunctionVariableNodeFactory.create(lookupResult); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java index 322b2dfc05..94bd2aa019 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java @@ -126,7 +126,7 @@ public abstract class RBuiltinPackage { List<Component> sources = rSources.get(getName()); if (sources != null) { for (Component src : sources) { - REngine.parseAndEval(src.libContents, frame, envForFrame, false); + RContext.getEngine().parseAndEval(src.libContents, frame, envForFrame, false); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java index 87159b8f4b..666355af5e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java @@ -41,7 +41,7 @@ public abstract class DoCall extends RBuiltinNode { @Specialization(guards = "lengthOne") public Object doDoCall(VirtualFrame frame, RAbstractStringVector fname, RList argsAsList, @SuppressWarnings("unused") REnvironment env) { - RFunction func = RContext.getLookup().lookup(fname.getDataAt(0)); + RFunction func = RContext.getEngine().lookupBuiltin(fname.getDataAt(0)); if (func == null) { throw RError.getGenericError(getEncapsulatingSourceSection(), "could not find function " + fname); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java index 4f14edb545..a7ac46878e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java @@ -71,9 +71,9 @@ public class EvalFunctions { try { Object result; if (expr instanceof RExpression) { - result = REngine.eval(getFunction(), (RExpression) expr, envir, REnvironment.emptyEnv()); + result = RContext.getEngine().eval(getFunction(), (RExpression) expr, envir, REnvironment.emptyEnv()); } else { - result = REngine.eval(getFunction(), (RLanguage) expr, envir, REnvironment.emptyEnv()); + result = RContext.getEngine().eval(getFunction(), (RLanguage) expr, envir, REnvironment.emptyEnv()); } return result; } catch (PutException x) { @@ -88,7 +88,7 @@ public class EvalFunctions { protected RFunction getFunction() { if (function == null) { - function = RContext.getLookup().lookup(getRBuiltin().name()); + function = RContext.getEngine().lookupBuiltin(getRBuiltin().name()); } return function; } @@ -114,7 +114,7 @@ public class EvalFunctions { * caller, so we can evaluate the promise using frame. */ controlVisibility(); - Object exprVal = REngine.evalPromise(expr, frame); + Object exprVal = RContext.getEngine().evalPromise(expr, frame); return doEvalBody(exprVal, envir, enclos); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java index 54925f0977..7ee760128d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java @@ -102,7 +102,7 @@ public abstract class Exists extends RBuiltinNode { if (!name.equals(lastName)) { CompilerDirectives.transferToInterpreterAndInvalidate(); lastName = name; - lastLookup = RContext.getLookup().lookup(name) != null; + lastLookup = RContext.getEngine().lookupBuiltin(name) != null; } // FIXME deal with changes in packages due to deleting symbols return lastLookup; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java index f712b25406..ae79b928c6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.RBuiltinKind.*; +import static com.oracle.truffle.r.runtime.RContext.Engine.ParseException; import java.io.*; @@ -30,7 +31,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.nodes.builtin.REngine.ParseException; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; @@ -91,7 +91,7 @@ public abstract class Parse extends RInvisibleBuiltinNode { @SlowPath private static RExpression doParse(String script) throws ParseException { - return REngine.parse(script); + return RContext.getEngine().parse(script); } @SlowPath diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java index f854294286..fbabf6f952 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java @@ -629,7 +629,6 @@ public abstract class PrettyPrinterNode extends RNode { if (re == null) { // the two are allocated side by side; checking for re is sufficient CompilerDirectives.transferToInterpreterAndInvalidate(); - RBuiltinPackages packages = (RBuiltinPackages) RContext.getLookup(); re = insert(ReFactory.create(new RNode[1], RBuiltinPackages.lookupBuiltin("Re"))); im = insert(ImFactory.create(new RNode[1], RBuiltinPackages.lookupBuiltin("Im"))); } @@ -665,7 +664,7 @@ public abstract class PrettyPrinterNode extends RNode { if (operand.getRowNames() == RNull.instance || ((RAbstractVector) operand.getRowNames()).getLength() == 0) { return "NULL\n<0 rows> (or 0-length row.names)"; } - RFunction getFunction = RContext.getLookup().lookup("get"); + RFunction getFunction = RContext.getEngine().lookupBuiltin("get"); RFunction formatFunction = (RFunction) indirectCall.call(frame, getFunction.getTarget(), RArguments.create(getFunction, REnvironment.globalEnv().getFrame(), new Object[]{"format.data.frame"})); return RRuntime.toString(indirectCall.call(frame, formatFunction.getTarget(), RArguments.create(formatFunction, new Object[]{operand}))); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java index cb7bf926ab..eba93720cc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java @@ -43,7 +43,7 @@ public abstract class ProcTime extends RBuiltinNode { public RDoubleVector procTime() { controlVisibility(); double[] data = new double[5]; - long nowInNanos = REngine.elapsedTimeInNanos(); + long nowInNanos = RContext.getEngine().elapsedTimeInNanos(); if (bean == null) { bean = ManagementFactory.getThreadMXBean(); } @@ -52,7 +52,7 @@ public abstract class ProcTime extends RBuiltinNode { data[0] = asDoubleSecs(userTimeInNanos); data[1] = asDoubleSecs(sysTimeInNanos); data[2] = asDoubleSecs(nowInNanos); - long[] childTimes = REngine.childTimesInNanos(); + long[] childTimes = RContext.getEngine().childTimesInNanos(); boolean na = childTimes[0] < 0 || childTimes[1] < 0; boolean complete = na ? RDataFactory.INCOMPLETE_VECTOR : RDataFactory.COMPLETE_VECTOR; data[3] = na ? RRuntime.DOUBLE_NA : asDoubleSecs(childTimes[0]); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/debug/DebugInfoBuiltin.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/debug/DebugInfoBuiltin.java index 821a2a2f3f..1c27d44a9e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/debug/DebugInfoBuiltin.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/debug/DebugInfoBuiltin.java @@ -40,7 +40,7 @@ public abstract class DebugInfoBuiltin extends RBuiltinNode { public Object printTree() { controlVisibility(); RContext.getInstance(); - RBuiltinPackages packages = (RBuiltinPackages) RContext.getLookup(); + RBuiltinPackages packages = RDefaultBuiltinPackages.getInstance(); StringBuilder b = new StringBuilder(); for (RBuiltinPackage pack : packages.getPackages()) { b.append(createPackageString(pack)); 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 d19ff45cf1..b4a52f879a 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 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.control.*; import com.oracle.truffle.r.runtime.*; @@ -42,12 +41,12 @@ public final class FunctionDefinitionNode extends RRootNode { private final String description; /** - * An instance of this node may be called from {@link REngine#runCall} with the intention to - * have its execution leave a footprint behind in a specific frame/environment, e.g., during - * library loading, commands from the shell, or R's {@code eval} and its friends. In that case, - * {@code substituteFrame} is {@code true}, and the {@link #execute(VirtualFrame)} method must - * be invoked with one argument, namely the {@link VirtualFrame} to be side-effected. Execution - * will then proceed in the context of that frame. + * An instance of this node may be called from with the intention to have its execution leave a + * footprint behind in a specific frame/environment, e.g., during library loading, commands from + * the shell, or R's {@code eval} and its friends. In that case, {@code substituteFrame} is + * {@code true}, and the {@link #execute(VirtualFrame)} method must be invoked with one + * argument, namely the {@link VirtualFrame} to be side-effected. Execution will then proceed in + * the context of that frame. */ private final boolean substituteFrame; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java index 9ce4ec2d8a..d3ada37db2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.runtime; -import java.io.*; import java.util.*; /** diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RBuiltinLookupProvider.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RBuiltinLookupProvider.java deleted file mode 100644 index 75d5fb4387..0000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RBuiltinLookupProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2014, 2014, 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.runtime; - -public interface RBuiltinLookupProvider { - RBuiltinLookup getRBuiltinLookup(); -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java index 60c3c41004..cd6aaf90d7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java @@ -25,12 +25,18 @@ package com.oracle.truffle.r.runtime; import java.util.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.r.runtime.REnvironment.*; import com.oracle.truffle.r.runtime.data.*; /** - * Helper class carrying state for an {@code REngine}. As per {@code REngine}, there is exactly one - * instance of this class, which is tied to the {@code REngine}. It has a separate existence to - * solve circularities in the current project structure. + * Provides access to the runtime state ("context") without being tied statically to a particular + * implementation of the runtime. + * + * The context provides two sub-interfaces {@link ConsoleHandler} and {@link Engine}that are + * (typically) implemented elsewhere, but accessed through {@link #getConsoleHandler()} and {@loink + * #getEngine()}, respectively. + * */ public final class RContext { @@ -86,6 +92,92 @@ public final class RContext { int getWidth(); } + public interface Engine { + /** + * Elapsed time of runtime. + * + * @return elapsed time in nanosecs. + */ + public long elapsedTimeInNanos(); + + /** + * Return user and system times for any spawned child processes in nanosecs, < 0 means not + * available (Windows). + */ + public long[] childTimesInNanos(); + + public static class ParseException extends Exception { + private static final long serialVersionUID = 1L; + + public ParseException(String msg) { + super(msg); + } + } + + /** + * Load a package from the default set of packages identified at startup. + * + * @param name name of the package, e.g. {@code base}, {@code stats}. + * @param frame for evaluating any associated R code + * @param envForFrame the namespace environment associated with the package. + */ + public void loadDefaultPackage(String name, VirtualFrame frame, REnvironment envForFrame); + + /** + * Return the {@link RFunction} for the builtin {@code name}. + * + */ + public RFunction lookupBuiltin(String name); + + /** + * Parse an R expression and return an {@link RExpression} object representing the Truffle + * ASTs for the components. + */ + public RExpression parse(String rscript) throws ParseException; + + /** + * Parse and evaluate {@code rscript} in {@code frame}. {@code printResult == true}, the + * result of the evaluation is printed to the console. + * + * @param envForFrame the environment that {@code frame} is bound to. + * @return the object returned by the evaluation or {@code null} if an error occurred. + */ + public Object parseAndEval(String rscript, VirtualFrame frame, REnvironment envForFrame, boolean printResult); + + /** + * + * This is intended for use by the unit test environment, where a "fresh" global environment + * is desired for each evaluation. + */ + public Object parseAndEvalTest(String rscript, boolean printResult); + + /** + * Support for the {@code eval} builtin using an {@link RExpression}. + * + * @param function identifies the eval variant, e.g. {@code local}, {@code eval}, + * {@code evalq} being invoked. + */ + public Object eval(RFunction function, RExpression expr, REnvironment envir, REnvironment enclos) throws PutException; + + /** + * Support for the {@code eval} builtin. This is tricky because the {@link Frame} "f" + * associated with {@code envir} has been materialized so we can't evaluate in it directly. + * Instead we create a new {@link VirtualFrame}, that is a logical clone of "f", evaluate in + * that, and then update "f" on return. + * + * @param function the actual function that invoked the "eval", e.g. {@code eval}, + * {@code evalq} , {@code local}. + */ + public Object eval(RFunction function, RLanguage expr, REnvironment envir, REnvironment enclos) throws PutException; + + /** + * Evaluate a promise in the given frame (for a builtin, where we can use the + * {@link VirtualFrame}) of the caller directly). + */ + public Object evalPromise(RPromise expr, VirtualFrame frame) throws RError; + + } + private final HashMap<Object, RFunction> cachedFunctions = new HashMap<>(); private final GlobalAssumptions globalAssumptions = new GlobalAssumptions(); private LinkedList<String> evalWarnings; @@ -101,10 +193,9 @@ public final class RContext { */ @CompilationFinal private boolean headless; - private static RBuiltinLookup lookup; - - private ConsoleHandler consoleHandler; - private String[] commandArgs; + @CompilationFinal private ConsoleHandler consoleHandler; + @CompilationFinal private String[] commandArgs; + @CompilationFinal private Engine engine; private static final RContext singleton = new RContext(); @@ -115,13 +206,12 @@ public final class RContext { return globalAssumptions; } - public static RContext linkRBuiltinLookupProvider(RBuiltinLookupProvider rbp) { - lookup = rbp.getRBuiltinLookup(); + public static RContext getInstance() { return singleton; } - public static RContext getInstance() { - return singleton; + public static Engine getEngine() { + return singleton.engine; } /** @@ -131,10 +221,12 @@ public final class RContext { * @param commandArgs * @param consoleHandler */ - public static void setRuntimeState(String[] commandArgs, ConsoleHandler consoleHandler, boolean headless) { + public static RContext setRuntimeState(Engine engine, String[] commandArgs, ConsoleHandler consoleHandler, boolean headless) { + singleton.engine = engine; singleton.commandArgs = commandArgs; singleton.consoleHandler = consoleHandler; singleton.headless = headless; + return singleton; } public static boolean isVisible() { @@ -149,13 +241,6 @@ public final class RContext { return singleton.headless; } - public static RBuiltinLookup getLookup() { - if (lookup == null) { - Utils.fail("no builtin lookup set"); - } - return lookup; - } - public ConsoleHandler getConsoleHandler() { if (consoleHandler == null) { Utils.fail("no console handler set"); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java index 7fd85d0b1a..c400db6580 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvironment.java @@ -228,7 +228,7 @@ public abstract class REnvironment implements RAttributable { initSearchList(); // load base package first - RPackages.loadBuiltin("base", baseFrame, baseEnv); + RContext.getEngine().loadDefaultPackage("base", baseFrame, baseEnv); } public static void packagesInitialize(ArrayList<RPackage> rPackages) { @@ -237,7 +237,7 @@ public abstract class REnvironment implements RAttributable { for (RPackage rPackage : rPackages) { VirtualFrame pkgFrame = RRuntime.createVirtualFrame(); Package pkgEnv = new Package(pkgParent, rPackage.name, pkgFrame, rPackage.path); - RPackages.loadBuiltin(rPackage.name, pkgFrame, pkgEnv); + RContext.getEngine().loadDefaultPackage(rPackage.name, pkgFrame, pkgEnv); attach(2, pkgEnv); pkgParent = pkgEnv; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java index eb07fe02f7..89884fe173 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RPackages.java @@ -66,19 +66,4 @@ public class RPackages { return packages; } - /** - * Purely a workaround for project circularity between nodes and runtime. - * - * @param envForFrame TODO - */ - public static void loadBuiltin(String name, VirtualFrame frame, REnvironment envForFrame) { - try { - Method loadMethod = Class.forName("com.oracle.truffle.r.nodes.builtin.RDefaultBuiltinPackages").getDeclaredMethod("load", String.class, VirtualFrame.class, REnvironment.class); - loadMethod.invoke(null, new Object[]{name, frame, envForFrame}); - } catch (Exception ex) { - ex.printStackTrace(); - Utils.fail("failed to load builtin package: " + name + ": " + ex); - } - } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/engine/REngine.java similarity index 79% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java rename to com.oracle.truffle.r.shell/src/com/oracle/truffle/r/engine/REngine.java index 42f8929f84..060819bdc0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/REngine.java +++ b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/engine/REngine.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin; +package com.oracle.truffle.r.engine; import java.io.*; import java.util.*; @@ -32,6 +32,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; +import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.parser.*; import com.oracle.truffle.r.parser.ast.*; @@ -45,21 +46,18 @@ import com.oracle.truffle.r.runtime.rng.*; * The engine for the FastR implementation. Handles parsing and evaluation. There is exactly one * instance of this class, stored in {link #singleton}. */ -public final class REngine implements RBuiltinLookupProvider { +public final class REngine implements RContext.Engine { private static REngine singleton = new REngine(); - private static final RContext context = RContext.linkRBuiltinLookupProvider(singleton); private static boolean crashOnFatalError; private static long startTime; private static long[] childTimes; + private static RContext context; + private static RBuiltinLookup builtinLookup; private REngine() { } - public RBuiltinLookup getRBuiltinLookup() { - return RDefaultBuiltinPackages.getInstance(); - } - /** * Initialize the engine. * @@ -76,7 +74,8 @@ public final class REngine implements RBuiltinLookupProvider { Locale.setDefault(Locale.ROOT); RPerfAnalysis.initialize(); crashOnFatalError = crashOnFatalErrorArg; - RContext.setRuntimeState(commandArgs, consoleHandler, headless); + builtinLookup = RDefaultBuiltinPackages.getInstance(); + context = RContext.setRuntimeState(singleton, commandArgs, consoleHandler, headless); VirtualFrame globalFrame = RRuntime.createVirtualFrame(); VirtualFrame baseFrame = RRuntime.createVirtualFrame(); REnvironment.baseInitialize(globalFrame, baseFrame); @@ -88,64 +87,51 @@ public final class REngine implements RBuiltinLookupProvider { ROptions.initialize(); RProfile.initialize(); // eval the system profile - REngine.parseAndEval(RProfile.systemProfile(), baseFrame, REnvironment.baseEnv(), false); + singleton.parseAndEval(RProfile.systemProfile(), baseFrame, REnvironment.baseEnv(), false); REnvironment.packagesInitialize(RPackages.initialize()); RPackageVariables.initialize(); // TODO replace with R code String siteProfile = RProfile.siteProfile(); if (siteProfile != null) { - REngine.parseAndEval(siteProfile, baseFrame, REnvironment.baseEnv(), false); + singleton.parseAndEval(siteProfile, baseFrame, REnvironment.baseEnv(), false); } String userProfile = RProfile.userProfile(); if (userProfile != null) { - REngine.parseAndEval(userProfile, globalFrame, REnvironment.globalEnv(), false); + singleton.parseAndEval(userProfile, globalFrame, REnvironment.globalEnv(), false); } return globalFrame; } - /** - * Elapsed time of process. - * - * @return elapsed time in nanosecs. - */ - public static long elapsedTimeInNanos() { - return System.nanoTime() - startTime; + public static REngine getInstance() { + return singleton; } - /** - * Return user and system times for any spawned child processes in nanosecs, < 0 means not - * available (Windows). - */ - public static long[] childTimesInNanos() { - return childTimes; + public void loadDefaultPackage(String name, VirtualFrame frame, REnvironment envForFrame) { + RDefaultBuiltinPackages.load(name, frame, envForFrame); } - public static RContext getContext() { - return context; + public RFunction lookupBuiltin(String name) { + return builtinLookup.lookup(name); } - /** - * Parse and evaluate {@code rscript} in {@code frame}. {@code printResult == true}, the result - * of the evaluation is printed to the console. - * - * @param envForFrame the environment that {@code frame} is bound to. - * @return the object returned by the evaluation or {@code null} if an error occurred. - */ - public static Object parseAndEval(String rscript, VirtualFrame frame, REnvironment envForFrame, boolean printResult) { + public long elapsedTimeInNanos() { + return System.nanoTime() - startTime; + } + + public long[] childTimesInNanos() { + return childTimes; + } + + public Object parseAndEval(String rscript, VirtualFrame frame, REnvironment envForFrame, boolean printResult) { return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<shell_input>"), frame, envForFrame, printResult); } - /** - * - * This is intended for use by the unit test environment, where a "fresh" global environment is - * desired for each evaluation. - */ - public static Object parseAndEvalTest(String rscript, boolean printResult) { + public Object parseAndEvalTest(String rscript, boolean printResult) { VirtualFrame frame = RRuntime.createVirtualFrame(); REnvironment.resetForTest(frame); return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<test_input>"), frame, REnvironment.globalEnv(), printResult); } - public static class ParseException extends Exception { + public class ParseException extends Exception { private static final long serialVersionUID = 1L; public ParseException(String msg) { @@ -153,11 +139,7 @@ public final class REngine implements RBuiltinLookupProvider { } } - /** - * Parse an R expression and return an {@link RExpression} object representing the Truffle ASTs - * for the components. - */ - public static RExpression parse(String rscript) throws ParseException { + public RExpression parse(String rscript) throws RContext.Engine.ParseException { try { Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<parse_input>")); ASTNode[] exprs = seq.getExprs(); @@ -167,16 +149,11 @@ public final class REngine implements RBuiltinLookupProvider { } return RDataFactory.createExpression(RDataFactory.createList(data)); } catch (RecognitionException ex) { - throw new ParseException(ex.getMessage()); + throw new RContext.Engine.ParseException(ex.getMessage()); } } - /** - * Support for the {@code eval} builtin using an {@link RExpression}. - * - * @param function TODO - */ - public static Object eval(RFunction function, RExpression expr, REnvironment envir, REnvironment enclos) throws PutException { + public Object eval(RFunction function, RExpression expr, REnvironment envir, REnvironment enclos) throws PutException { Object result = null; for (int i = 0; i < expr.getLength(); i++) { result = eval(function, (RLanguage) expr.getDataAt(i), envir, enclos); @@ -184,16 +161,7 @@ public final class REngine implements RBuiltinLookupProvider { return result; } - /** - * Support for the {@code eval} builtin. This is tricky because the {@link Frame} "f" associated - * with {@code envir} has been materialized so we can't evaluate in it directly. Instead we - * create a new {@link VirtualFrame}, that is a logical clone of "f", evaluate in that, and then - * update "f" on return. - * - * @param function the actual function that invoked the "eval", e.g. {@code eval}, {@code evalq} - * , {@code local}. - */ - public static Object eval(RFunction function, RLanguage expr, REnvironment envir, @SuppressWarnings("unused") REnvironment enclos) throws PutException { + public Object eval(RFunction function, RLanguage expr, REnvironment envir, REnvironment enclos) throws PutException { RootCallTarget callTarget = makeCallTarget((RNode) expr.getRep(), REnvironment.globalEnv()); MaterializedFrame envFrame = envir.getFrame(); VirtualFrame vFrame = RRuntime.createVirtualFrame(); @@ -240,11 +208,7 @@ public final class REngine implements RBuiltinLookupProvider { return result; } - /** - * Evaluate a promise in the given frame (for a builtin, where we can use the - * {@link VirtualFrame}) of the caller directly). - */ - public static Object evalPromise(RPromise expr, VirtualFrame frame) throws RError { + public Object evalPromise(RPromise expr, VirtualFrame frame) throws RError { RootCallTarget callTarget = makeCallTarget((RNode) expr.getRep(), REnvironment.emptyEnv()); return expr.setValue(runCall(callTarget, frame, false, false)); } @@ -333,7 +297,8 @@ public final class REngine implements RBuiltinLookupProvider { private static void printResult(Object result) { if (RContext.isVisible()) { - RFunction function = RContext.getLookup().lookup("print"); + // TODO cache this + RFunction function = builtinLookup.lookup("print"); function.getTarget().call(RArguments.create(function, new Object[]{result})); } } diff --git a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java index 38766750f8..eb484ab105 100644 --- a/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java +++ b/com.oracle.truffle.r.shell/src/com/oracle/truffle/r/shell/RCommand.java @@ -28,7 +28,7 @@ import java.io.*; import java.util.*; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.engine.*; import com.oracle.truffle.r.runtime.*; import jline.console.*; @@ -145,7 +145,7 @@ public class RCommand { String content = new String(bytes); JLineConsoleHandler consoleHandler = new JLineConsoleHandler(false, new ConsoleReader(null, System.out)); VirtualFrame frame = REngine.initialize(commandArgs, consoleHandler, true, true); - REngine.parseAndEval(content, frame, REnvironment.globalEnv(), true); + REngine.getInstance().parseAndEval(content, frame, REnvironment.globalEnv(), true); } catch (IOException ex) { Utils.fail("unexpected error reading file input"); } @@ -168,7 +168,7 @@ public class RCommand { continue; } - REngine.parseAndEval(line, globalFrame, REnvironment.globalEnv(), true); + REngine.getInstance().parseAndEval(line, globalFrame, REnvironment.globalEnv(), true); } } catch (UserInterruptException e) { // interrupted diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java index bce98f4cb1..d38518f577 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java @@ -22,7 +22,7 @@ */ package com.oracle.truffle.r.test.generate; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.engine.*; import com.oracle.truffle.r.runtime.*; public class FastRSession implements RSession { @@ -87,7 +87,7 @@ public class FastRSession implements RSession { public String eval(String expression) { consoleHandler.reset(); - REngine.parseAndEvalTest(expression, true); + REngine.getInstance().parseAndEvalTest(expression, true); return consoleHandler.buffer.toString(); } diff --git a/mx.fastr/projects b/mx.fastr/projects index 56cabdd66d..b52e410686 100644 --- a/mx.fastr/projects +++ b/mx.fastr/projects @@ -92,7 +92,7 @@ project@com.oracle.truffle.r.test.ignore.processor@workingSets=Truffle,FastR # com.oracle.truffle.r.test project@com.oracle.truffle.r.test@sourceDirs=src -project@com.oracle.truffle.r.test@dependencies=com.oracle.truffle.r.nodes,JUNIT +project@com.oracle.truffle.r.test@dependencies=com.oracle.truffle.r.nodes,com.oracle.truffle.r.shell,JUNIT project@com.oracle.truffle.r.test@checkstyle=com.oracle.truffle.r.runtime project@com.oracle.truffle.r.test@javaCompliance=1.8 project@com.oracle.truffle.r.test@annotationProcessors=com.oracle.truffle.r.test.ignore.processor -- GitLab