From 155f8b3c082614380116e86e9e371aaec93fe47a Mon Sep 17 00:00:00 2001 From: Florian Angerer <florian.angerer@oracle.com> Date: Wed, 31 May 2017 15:32:43 +0200 Subject: [PATCH] Implemented srcref for block statements. --- .../oracle/truffle/r/runtime/RSerialize.java | 55 +++++++---- .../com/oracle/truffle/r/runtime/RSrcref.java | 94 ++++++++++++++++++- 2 files changed, 130 insertions(+), 19 deletions(-) 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 63106513ce..0ff77a7e35 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 @@ -1759,11 +1759,13 @@ public class RSerialize { if (outAttrs != null) { SourceSection ss = outAttrs.getSourceReferenceAttributes(); if (ss != null) { - String path = ss.getSource().getURI().getPath(); - REnvironment createSrcfile = RSrcref.createSrcfile(path); - Object createLloc = RSrcref.createLloc(ss, createSrcfile); - writePairListEntry(RRuntime.R_SRCREF, createLloc); - writePairListEntry(RRuntime.R_SRCFILE, createSrcfile); + String path = RSource.getPathInternal(ss.getSource()); + if (path != null) { + REnvironment createSrcfile = RSrcref.createSrcfile(path); + Object createLloc = RSrcref.createLloc(ss, createSrcfile); + writePairListEntry(RRuntime.R_SRCREF, createLloc); + writePairListEntry(RRuntime.R_SRCFILE, createSrcfile); + } } DynamicObject attributes = outAttrs.getExplicitAttributes(); if (attributes != null) { @@ -2094,13 +2096,7 @@ public class RSerialize { private DynamicObject explicitAttributes; private SourceSection ss; - OutAttributes(RAttributable obj, SEXPTYPE type) { - - explicitAttributes = obj.getAttributes(); - initSourceSection(obj, type); - } - - OutAttributes(Object obj, SEXPTYPE type) { + private OutAttributes(Object obj, SEXPTYPE type) { if (obj instanceof RAttributable) { explicitAttributes = ((RAttributable) obj).getAttributes(); @@ -2112,10 +2108,14 @@ public class RSerialize { if (type == SEXPTYPE.FUNSXP) { RFunction fun = (RFunction) obj; RSyntaxFunction body = (RSyntaxFunction) fun.getRootNode(); - SourceSection lazySourceSection = body.getLazySourceSection(); - if (lazySourceSection != RSyntaxNode.LAZY_DEPARSE) { - ss = lazySourceSection; - } + setSourceSection(body); + } + } + + private void setSourceSection(RSyntaxElement body) { + SourceSection lazySourceSection = body.getLazySourceSection(); + if (lazySourceSection != RSyntaxNode.LAZY_DEPARSE) { + ss = lazySourceSection; } } @@ -2315,7 +2315,6 @@ public class RSerialize { @Override protected Void visit(RSyntaxLookup element) { -// setSrcrefs(element) state.setCarAsSymbol(element.getIdentifier()); return null; } @@ -2410,7 +2409,27 @@ public class RSerialize { private static void serializeFunctionDefinition(State state, RSyntaxFunction function) { SerializeVisitor visitor = new SerializeVisitor(state); state.setCar(visitor.visitFunctionFormals(function)); - state.setCdr(visitor.visitFunctionBody(function)); + Object visitFunctionBody = visitor.visitFunctionBody(function); + + // convert and attach source section to srcref attribute + if (visitFunctionBody instanceof RAttributable) { + + SourceSection lazySourceSection = function.getLazySourceSection(); + if (lazySourceSection != null) { + String pathInternal = RSource.getPathInternal(lazySourceSection.getSource()); + if (pathInternal != null) { + RAttributable visitFunctionBody2 = (RAttributable) visitFunctionBody; + RList createBlockSrcrefs = RSrcref.createBlockSrcrefs(function); + if (createBlockSrcrefs != null) { + visitFunctionBody2.setAttr(RRuntime.R_SRCREF, createBlockSrcrefs); + visitFunctionBody2.setAttr(RRuntime.R_WHOLE_SRCREF, RSrcref.createLloc(lazySourceSection)); + visitFunctionBody2.setAttr(RRuntime.R_SRCFILE, RSrcref.createSrcfile(pathInternal)); + } + } + } + } + + state.setCdr(visitFunctionBody); } private static Object serializeLanguage(State state, RLanguage lang) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java index 247bf965ad..f107a449ad 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java @@ -18,6 +18,8 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFileAttributes; +import java.util.LinkedList; +import java.util.List; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.source.Source; @@ -25,6 +27,7 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -32,7 +35,13 @@ import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; +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; /** * Utilities for handling R srcref attributes, in particular conversion from {@link Source}, @@ -103,6 +112,88 @@ public class RSrcref { return createLloc(ss, createSrcfile(path)); } + /** + * Creates a block source reference or {@code null} if the function's body is not a block + * statement.<br> + * Srcref for blocks are different in that it is an RList of srcref vectors whereas each element + * corresponds to one syntax call in the block (including the block itself). E.g. + * <p> + * <code> {<br/> + * print('Hello')<br/> + * print(x)<br/> + * }</code> + * </p> + * will result in [[1, 20, 4, 1, 20, 1, 1, 4], [2, 2, 2, 15, 2, 15, 2, 2], [3, 2, 3, 9, 2, 9, 3, + * 3]] + * + * @param function + */ + @TruffleBoundary + public static RList createBlockSrcrefs(RSyntaxFunction function) { + + List<Object> blockSrcrefs = new LinkedList<>(); + + RSyntaxVisitor<Void> v = new RSyntaxVisitor<Void>() { + + private int depth = 0; + + @Override + public Void visit(RSyntaxCall element) { + + if (depth == 0 && !isBlockStatement(element)) { + return null; + } + + SourceSection lazySourceSection = element.getLazySourceSection(); + if (lazySourceSection != null) { + blockSrcrefs.add(createLloc(lazySourceSection)); + } + + if (depth == 0) { + RSyntaxElement[] syntaxArguments = element.getSyntaxArguments(); + for (int i = 0; i < syntaxArguments.length; i++) { + if (syntaxArguments[i] != null) { + depth++; + accept(syntaxArguments[i]); + depth--; + } + } + } + return null; + } + + private boolean isBlockStatement(RSyntaxCall element) { + RSyntaxElement lhs = element.getSyntaxLHS(); + if (lhs instanceof RSyntaxLookup) { + return "{".equals(((RSyntaxLookup) lhs).getIdentifier()); + } + return false; + } + + @Override + public Void visit(RSyntaxConstant element) { + return null; + } + + @Override + public Void visit(RSyntaxLookup element) { + return null; + } + + @Override + public Void visit(RSyntaxFunction element) { + accept(element.getSyntaxBody()); + return null; + } + }; + v.accept(function); + + if (!blockSrcrefs.isEmpty()) { + return RDataFactory.createList(blockSrcrefs.toArray()); + } + return null; + } + @TruffleBoundary public static Object createLloc(SourceSection src) { if (src == null) { @@ -117,7 +208,8 @@ public class RSrcref { env = RDataFactory.createNewEnv("src"); env.setClassAttr(RDataFactory.createStringVector(new String[]{"srcfilecopy", RRuntime.R_SRCFILE}, true)); try { - Path path = Paths.get(RSource.getPathInternal(source)); + String pathStr = RSource.getPathInternal(source); + Path path = Paths.get(pathStr != null ? pathStr : ""); env.put(SrcrefFields.filename.name(), path.toString()); env.put(SrcrefFields.fixedNewlines.name(), RRuntime.LOGICAL_TRUE); String[] lines = new String[source.getLineCount()]; -- GitLab