From eb55b547993edc5384292eabd51bdb142754bd15 Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Tue, 3 Mar 2015 18:07:54 -0800 Subject: [PATCH] All parsing now uses Source objects. Rewrite parse builtin to do best effort Source creation and also create standard srcref attribute --- .../com/oracle/truffle/r/engine/REngine.java | 16 +- .../builtin/base/ConnectionFunctions.java | 3 +- .../truffle/r/nodes/builtin/base/Lapply.java | 10 +- .../truffle/r/nodes/builtin/base/Parse.java | 208 +++++++++++++++--- .../truffle/r/nodes/RTruffleVisitor.java | 4 +- .../truffle/r/nodes/control/BreakNode.java | 3 - .../truffle/r/nodes/control/NextNode.java | 3 - .../r/nodes/instrument/RNodeTimer.java | 16 +- .../r/nodes/runtime/RASTHelperImpl.java | 3 +- .../oracle/truffle/r/runtime/RContext.java | 9 +- .../oracle/truffle/r/runtime/RSerialize.java | 4 +- .../r/runtime/conn/ConnectionSupport.java | 10 + 12 files changed, 219 insertions(+), 70 deletions(-) diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index ce6a417c4d..30068d4419 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.library.graphics.*; import com.oracle.truffle.r.nodes.*; @@ -210,18 +209,9 @@ public final class REngine implements RContext.Engine { } } - public Node parseSingle(String singleExpression) { + public RExpression parse(Source source) throws RContext.Engine.ParseException { try { - Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(singleExpression), Source.asPseudoFile(singleExpression, "<parse_input>")); - return transform(seq.getExpressions()[0]); - } catch (RecognitionException ex) { - throw Utils.fatalError("parseSingle failed"); - } - } - - public RExpression parse(String rscript) throws RContext.Engine.ParseException { - try { - Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(rscript), Source.asPseudoFile(rscript, "<parse_input>")); + Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(source.getCode()), source); ASTNode[] exprs = seq.getExpressions(); Object[] data = new Object[exprs.length]; for (int i = 0; i < exprs.length; i++) { @@ -463,7 +453,7 @@ public final class REngine implements RContext.Engine { } // Only relevant when running without base package loaded - private static final String INTERNAL_PRINT = ".print.internal <- function(x) { .Internal(print.default(x, NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE))" + "}"; + private static final Source INTERNAL_PRINT = Source.asPseudoFile(".print.internal <- function(x) { .Internal(print.default(x, NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE))}", "<internal_print>"); @CompilationFinal private static RFunction printInternal; private static RFunction getPrintInternal() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java index 11cddcbd99..0a63fefd31 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java @@ -96,8 +96,9 @@ public abstract class ConnectionFunctions { if (!RRuntime.fromLogical(blocking)) { throw RError.nyi(getEncapsulatingSourceSection(), " non-blocking mode not supported"); } + String path = removeFileURLPrefix(description.getDataAt(0)); try { - return new FileRConnection(description.getDataAt(0), open.getDataAt(0)); + return new FileRConnection(path, open.getDataAt(0)); } catch (IOException ex) { RError.warning(RError.Message.CANNOT_OPEN_FILE, description.getDataAt(0), ex.getMessage()); throw RError.error(getEncapsulatingSourceSection(), RError.Message.CANNOT_OPEN_CONNECTION); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index 3a31e7bab6..a05546ed26 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -20,6 +20,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.*; 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.access.*; import com.oracle.truffle.r.nodes.access.array.read.*; @@ -30,6 +31,7 @@ import com.oracle.truffle.r.nodes.builtin.base.Lapply.GeneralLApplyNode.LapplyIt import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.nodes.function.MatchedArguments.MatchedArgumentsNode; import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.RContext.Engine.ParseException; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.*; @@ -115,6 +117,7 @@ public abstract class Lapply extends RBuiltinNode { */ protected static class LapplyIteratorNode extends RNode { private static final String ITER_INDEX_NAME = AnonymousFrameVariable.create("LAPPLY_ITER_INDEX"); + private static final Source ACCESS_ARRAY_SOURCE = Source.asPseudoFile("X[[i]]", "<lapply_array_access>"); /** * Increments the iterator index, updating the {@link #ITER_INDEX_NAME} variable. Always @@ -147,7 +150,12 @@ public abstract class Lapply extends RBuiltinNode { RNode getIndexedLoad() { if (indexedLoad == null) { - AccessArrayNode indexNode = (AccessArrayNode) RContext.getEngine().parseSingle("X[[i]]"); + AccessArrayNode indexNode; + try { + indexNode = (AccessArrayNode) ((RLanguage) RContext.getEngine().parse(ACCESS_ARRAY_SOURCE).getDataAt(0)).getRep(); + } catch (ParseException ex) { + throw RInternalError.shouldNotReachHere(); + } REnvironment env = RDataFactory.createNewEnv("dummy"); env.safePut("i", RDataFactory.createLanguage(ReadVariableNode.create(ITER_INDEX_NAME, false))); indexedLoad = indexNode.substitute(env); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java index 606e346ad2..42ca5dd6dd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java @@ -26,14 +26,20 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.*; import java.io.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.unary.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RContext.Engine.ParseException; import com.oracle.truffle.r.runtime.conn.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.*; +import com.oracle.truffle.r.runtime.env.*; /** * Internal component of the {@code parse} base package function. @@ -43,55 +49,111 @@ import com.oracle.truffle.r.runtime.data.model.*; * </pre> * * TODO handle case when {@code srcFile != NULL}; + * + * There are two main modalities in the arguments: + * <ul> + * <li>Input is taken from "conn" or "text" (in which case conn==stdin(), but ignored).</li> + * <li>Parse the entire input or just "n" "expressions". The FastR parser cannot handle the latter + * case properly. It will parse the entire stream whereas GnuR stops after "n" expressions. So, + * e.g., if there is a syntax error after the "n'th" expression, GnuR does not see it, whereas FastR + * does and throws an error. However, if there is no error FastR can truncate the expressions vector + * to length "n"</li> + * </ul> + * Despite the modality there is no value in multiple specializations for what is an inherently + * slow-path builtin. + * <p> + * The inputs do not lend themselves to the correct creation of {@link Source} attributes for the + * FastR AST. In particular the {@code source} builtin reads the input internally and calls us the + * "text" variant. However useful information regarding the origin of the input can be found either + * in the connection info or in the "srcfile" argument which, if not {@code RNull#instance} is an + * {@link REnvironment} with relevant data. So we can fix up the {@link Source} attributes on the + * AST after the parse. It's relevant to do this for the Truffle instrumentation framework. + * <p> + * On the R side, GnuR adds similar R attributes to the result, which is important for R tooling. */ @RBuiltin(name = "parse", kind = INTERNAL, parameterNames = {"conn", "n", "text", "prompt", "srcfile", "encoding"}) public abstract class Parse extends RBuiltinNode { + @Child private CastIntegerNode castIntNode; + @Child private CastStringNode castStringNode; + @Child private CastToVectorNode castVectorNode; - @SuppressWarnings("unused") - @Specialization - protected Object parse(RConnection conn, RNull n, RNull text, String prompt, Object srcFile, String encoding) { - controlVisibility(); - try { - String[] lines = conn.readLines(0); - return doParse(coalesce(lines)); - } catch (IOException | ParseException ex) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.PARSE_ERROR); + private int castInt(VirtualFrame frame, Object n) { + if (castIntNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castIntNode = insert(CastIntegerNodeGen.create(null, false, false, false)); + } + int result = (int) castIntNode.executeInt(frame, n); + if (RRuntime.isNA(result)) { + result = -1; } + return result; + } + + private RStringVector castString(VirtualFrame frame, Object s) { + if (castStringNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castVectorNode = insert(CastToVectorNodeGen.create(null, false, false, false, false)); + castStringNode = insert(CastStringNodeGen.create(null, false, false, false, false)); + } + return (RStringVector) castStringNode.executeString(frame, castVectorNode.executeObject(frame, s)); } - @SuppressWarnings("unused") @Specialization - protected Object parse(RConnection conn, double n, RNull text, String prompt, Object srcFile, String encoding) { + protected Object parse(VirtualFrame frame, RConnection conn, Object n, Object text, RAbstractStringVector prompt, Object srcFile, RAbstractStringVector encoding) { controlVisibility(); - try { - String[] lines = conn.readLines((int) n); - return doParse(coalesce(lines)); - } catch (IOException | ParseException ex) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.PARSE_ERROR); + int nAsInt; + if (n != RNull.instance) { + nAsInt = castInt(frame, n); + } else { + nAsInt = -1; + } + Object textVec = text; + if (textVec != RNull.instance) { + textVec = castString(frame, textVec); } + return doParse(conn, nAsInt, textVec, prompt, srcFile, encoding); } + @TruffleBoundary @SuppressWarnings("unused") - @Specialization(guards = "parseEntire") - protected Object parse(RConnection conn, Object n, RAbstractStringVector textVec, String prompt, Object srcFile, String encoding) { - controlVisibility(); - String text = coalesce(((RStringVector) textVec).getDataWithoutCopying()); - if (text.length() == 0) { + private Object doParse(RConnection conn, int n, Object textVec, RAbstractStringVector prompt, Object srcFile, RAbstractStringVector encoding) { + String[] lines; + if (textVec == RNull.instance) { + if (conn == StdConnections.getStdin()) { + throw RError.nyi(getEncapsulatingSourceSection(), " parse from stdin not implemented"); + } + try (RConnection openConn = conn.forceOpen("r")) { + lines = openConn.readLines(0); + } catch (IOException ex) { + throw RError.error(getEncapsulatingSourceSection(), RError.Message.PARSE_ERROR); + } + } else { + lines = ((RStringVector) textVec).getDataWithoutCopying(); + } + String coalescedLines = coalesce(lines); + if (coalescedLines.length() == 0 || n == 0) { return RDataFactory.createExpression(RDataFactory.createList()); } try { - return doParse(text); + Source source = srcFile != RNull.instance ? createSource(srcFile, coalescedLines) : createSource(conn); + RExpression exprs = RContext.getEngine().parse(source); + if (n > 0 && n > exprs.getLength()) { + RList list = exprs.getList(); + Object[] listData = list.getDataCopy(); + Object[] subListData = new Object[n]; + System.arraycopy(listData, 0, subListData, 0, n); + exprs = RDataFactory.createExpression(RDataFactory.createList(subListData)); + } + // Handle the required R attributes + if (srcFile instanceof REnvironment) { + addAttributes(exprs, source, (REnvironment) srcFile); + } + return exprs; } catch (ParseException ex) { throw RError.error(getEncapsulatingSourceSection(), RError.Message.PARSE_ERROR); } } - @TruffleBoundary - private static RExpression doParse(String script) throws ParseException { - return RContext.getEngine().parse(script); - } - - @TruffleBoundary private static String coalesce(String[] lines) { StringBuffer sb = new StringBuffer(); for (String line : lines) { @@ -101,16 +163,90 @@ public abstract class Parse extends RBuiltinNode { return sb.toString(); } - public static boolean parseEntire(@SuppressWarnings("unused") Object conn, Object n) { - if (n == RNull.instance) { - return true; - } else if (n instanceof Double && (((Double) n == -1 || ((Double) n) == RRuntime.DOUBLE_NA))) { - return true; - } else if (n instanceof Integer && (((Integer) n == -1 || ((Integer) n) == RRuntime.INT_NA))) { - return true; + /** + * Creates a {@link Source} object by gleaning information from {@code srcFile}. + */ + private static Source createSource(Object srcFile, String coalescedLines) { + if (srcFile instanceof REnvironment) { + REnvironment srcFileEnv = (REnvironment) srcFile; + boolean isFile = RRuntime.fromLogical((byte) srcFileEnv.get("isFile")); + if (isFile) { + // Might be a URL + String fileName = ConnectionSupport.removeFileURLPrefix((String) srcFileEnv.get("filename")); + File fnf = new File(fileName); + String path = null; + if (!fnf.isAbsolute()) { + String wd = RRuntime.asString(srcFileEnv.get("wd")); + path = String.join(File.separator, wd, fileName); + } else { + path = fileName; + } + return createFileSource(path); + } else { + return Source.asPseudoFile(coalescedLines, "<parse>"); + } } else { - return false; + String srcFileText = RRuntime.asString(srcFile); + if (srcFileText.equals("<text>")) { + return Source.asPseudoFile(coalescedLines, "<parse>"); + } else { + return createFileSource(ConnectionSupport.removeFileURLPrefix(srcFileText)); + } } + + } + + private static Source createSource(RConnection conn) { + // TODO check if file + String path = ConnectionSupport.getBaseConnection(conn).getSummaryDescription(); + return createFileSource(path); + } + + private static Source createFileSource(String path) { + try { + /* + * Although we have read the source, it will be re-read in parse as there is currently + * no way to pass the source we have to Source.fromFileName. + */ + return Source.fromFileName(path); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + } + + private static void addAttributes(RExpression exprs, Source source, REnvironment srcFile) { + Object[] srcrefData = new Object[exprs.getLength()]; + for (int i = 0; i < srcrefData.length; i++) { + Node node = (Node) ((RLanguage) exprs.getDataAt(i)).getRep(); + SourceSection ss = node.getSourceSection(); + int[] llocData = new int[8]; + int startLine = ss.getStartLine(); + int startColumn = ss.getStartColumn(); + int lastLine = source.getLineNumber(ss.getCharEndIndex()); + int lastColumn = source.getColumnNumber(ss.getCharEndIndex()) - 1; + // no multi-byte support, so byte==line + llocData[0] = startLine; + llocData[1] = startColumn; + llocData[2] = lastLine; + llocData[3] = lastColumn; + llocData[4] = startColumn; + llocData[5] = lastColumn; + llocData[6] = startLine; + llocData[7] = lastLine; + RIntVector lloc = RDataFactory.createIntVector(llocData, RDataFactory.COMPLETE_VECTOR); + srcrefData[i] = lloc; + } + exprs.setAttr("srcref", RDataFactory.createList(srcrefData)); + int[] wholeSrcrefData = new int[8]; + int endOffset = source.getCode().length() - 1; + wholeSrcrefData[0] = source.getLineNumber(0); + wholeSrcrefData[3] = source.getLineNumber(endOffset); + source.getColumnNumber(0); + wholeSrcrefData[6] = wholeSrcrefData[0]; + wholeSrcrefData[6] = wholeSrcrefData[3]; + + exprs.setAttr("wholeSrcref", RDataFactory.createIntVector(wholeSrcrefData, RDataFactory.COMPLETE_VECTOR)); + exprs.setAttr("srcfile", srcFile); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java index f1b7a1ec4f..7620a280d3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java @@ -630,12 +630,12 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> { @Override public RNode visit(Break n) { - return new BreakNode(); + return new BreakNode(n.getSource()); } @Override public RNode visit(Next n) { - return new NextNode(); + return new NextNode(n.getSource()); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java index 44a00eaf1d..6adc03edc2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BreakNode.java @@ -29,9 +29,6 @@ import com.oracle.truffle.r.runtime.RDeparse.*; public final class BreakNode extends RNode { - public BreakNode() { - } - public BreakNode(SourceSection src) { assignSourceSection(src); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java index d6e940632d..71473aef1a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/NextNode.java @@ -29,9 +29,6 @@ import com.oracle.truffle.r.runtime.RDeparse.State; public final class NextNode extends RNode { - public NextNode() { - } - public NextNode(SourceSection src) { assignSourceSection(src); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrument/RNodeTimer.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrument/RNodeTimer.java index 92eedfa28b..72de66a845 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrument/RNodeTimer.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrument/RNodeTimer.java @@ -28,7 +28,9 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.impl.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.*; +import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; /** @@ -128,7 +130,19 @@ public class RNodeTimer { data.toArray(sortedData); Arrays.sort(sortedData); for (StatementData sd : sortedData) { - System.out.printf("%10d: %s%n", sd.time, sd.node.getSourceSection().getCode()); + System.out.printf("%10d: %s%n", sd.time, safeGetCode(sd.node)); + } + } + + private static String safeGetCode(Node node) { + SourceSection ss = node.getSourceSection(); + if (ss != null) { + return ss.getCode(); + } else { + FunctionDefinitionNode rootNode = (FunctionDefinitionNode) node.getRootNode(); + RDeparse.State state = RDeparse.State.createPrintableState(); + rootNode.deparse(state); + return state.toString(); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java index 97fb50c3a7..ba50c1f4a1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java @@ -256,6 +256,7 @@ public class RASTHelperImpl implements RASTHelper { RASTDeparse.deparse(state, f); } + private static final Source GET_NAMESPACE_SOURCE = Source.asPseudoFile("..getNamespace(name)", "<..getNamespace>"); private static RCallNode getNamespaceCall; /** @@ -265,7 +266,7 @@ public class RASTHelperImpl implements RASTHelper { public REnvironment findNamespace(RStringVector name, int depth) { if (getNamespaceCall == null) { try { - getNamespaceCall = (RCallNode) ((RLanguage) RContext.getEngine().parse("..getNamespace(name)").getDataAt(0)).getRep(); + getNamespaceCall = (RCallNode) ((RLanguage) RContext.getEngine().parse(GET_NAMESPACE_SOURCE).getDataAt(0)).getRep(); } catch (ParseException ex) { // most unexpected Utils.fail("findNameSpace"); 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 73869dd34c..e0bcf80988 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 @@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RPromise.Closure; @@ -161,13 +160,7 @@ public final class RContext extends ExecutionContext { * Parse an R expression and return an {@link RExpression} object representing the Truffle * ASTs for the components. */ - RExpression parse(String rscript) throws ParseException; - - /** - * Evaluates a single R expression and returns the AST node for it, For internal use. Parse - * errors are fatal. - */ - Node parseSingle(String singleExpression); + RExpression parse(Source source) throws ParseException; /** * Parse and evaluate {@code rscript} in {@code frame}. {@code printResult == true}, the diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 2f1fed3cb6..4faf59805f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -15,6 +15,7 @@ import java.io.*; import java.util.*; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.options.*; import com.oracle.truffle.r.runtime.conn.*; import com.oracle.truffle.r.runtime.data.*; @@ -358,7 +359,8 @@ public class RSerialize { * there (and overwrite the promise), so we fix the enclosing frame up * on return. */ - RExpression expr = RContext.getEngine().parse(deparse); + Source source = Source.asPseudoFile(deparse, "<package deparse>"); + RExpression expr = RContext.getEngine().parse(source); RFunction func = (RFunction) RContext.getEngine().eval(expr, RDataFactory.createNewEnv(REnvironment.emptyEnv(), 0), depth + 1); func.setEnclosingFrame(((REnvironment) rpl.getTag()).getFrame()); result = func; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java index ad61813fff..3c780a2d48 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java @@ -181,6 +181,16 @@ public class ConnectionSupport { } + public static final String FILE_URL_PREFIX = "file://"; + + public static String removeFileURLPrefix(String path) { + if (path.startsWith(FILE_URL_PREFIX)) { + return path.replace(FILE_URL_PREFIX, ""); + } else { + return path; + } + } + // TODO implement all open modes /** -- GitLab