# HG changeset patch # User Michael Van De Vanter # Date 1447213357 28800 # Node ID ad180d3d4bd780475281d43c47ab0c125bea4646 # Parent a8b796ac350da46c4fa103c6415c7a6fe34932ed# Parent fa1061fb21fa5e69d4108201e9544d550a0fa036 Merge with fa1061fb21fa5e69d4108201e9544d550a0fa036 diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Tue Nov 10 19:42:37 2015 -0800 @@ -482,14 +482,19 @@ @Override protected Object evalInContext(Object vm, SuspendedEvent ev, String code, FrameInstance frame) throws IOException { - Node n = frame == null ? ev.getNode() : frame.getCallNode(); + Node n = ev.getNode(); + if (n == null && frame != null) { + n = frame.getCallNode(); + } + if (n == null) { + throw new IOException("Can't determine language for text \"" + code + "\""); + } RootNode rootNode = n.getRootNode(); Class languageType = findLanguage(rootNode); - Env env = findLanguage(vm, languageType); - TruffleLanguage lang = findLanguage(env); - Source source = Source.fromText(code, "eval in context"); - CallTarget target = lang.parse(source, n); - return target.call(); + final Env env = findLanguage(vm, languageType); + final TruffleLanguage lang = findLanguage(env); + final Source source = Source.fromText(code, "eval in context"); + return lang.evalInContext(source, n, frame.getFrame(null, true).materialize()); } @Override diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Tue Nov 10 19:42:37 2015 -0800 @@ -24,6 +24,11 @@ */ package com.oracle.truffle.api.debug; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameInstance; @@ -31,10 +36,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.instrument.StandardSyntaxTag; import com.oracle.truffle.api.nodes.Node; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; /** * This event is delivered to all @@ -52,6 +53,7 @@ private final MaterializedFrame mFrame; private final Node astNode; private final List frames; + private final int stackSize; private final Debugger debugger; SuspendedEvent(Debugger prepares, Node astNode, MaterializedFrame mFrame, List recentWarnings, final int stackDepth) { @@ -77,7 +79,7 @@ return frameInstance; } }); - + stackSize = frames.size(); } /** @@ -198,13 +200,20 @@ * Evaluates given code snippet in the context of currently suspended execution. * * @param code the snippet to evaluate - * @param frame null in case the evaluation should happen in top most frame, + * @param frameNumber null in case the evaluation should happen in top most frame, * non-null value to specify a frame from those {@link #getStack() currently on * stack} to perform the evaluation in context of * @return the computed value * @throws IOException in case an evaluation goes wrong */ - public Object eval(String code, FrameInstance frame) throws IOException { - return debugger.evalInContext(this, code, frame); + public Object eval(String code, Integer frameNumber) throws IOException { + int n = 0; + if (frameNumber != null) { + if (frameNumber < 0 || frameNumber >= stackSize) { + throw new IOException("invalid frame number"); + } + n = frameNumber; + } + return debugger.evalInContext(this, code, frames.get(n)); } } diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Tue Nov 10 19:42:37 2015 -0800 @@ -316,10 +316,6 @@ return API.findContext(env); } - protected TruffleLanguage findLanguage(Env env) { - return API.findLanguage(env); - } - /** Applies all registered {@linkplain ASTProber probers} to the AST. */ protected void probeAST(RootNode rootNode) { INSTRUMENT.probeAST(rootNode); @@ -335,6 +331,10 @@ return parse(truffleLanguage, code, context, argumentNames); } + protected TruffleLanguage findLanguage(Env env) { + return API.findLanguage(env); + } + protected CallTarget parse(TruffleLanguage truffleLanguage, Source code, Node context, String... argumentNames) throws IOException { return API.parse(truffleLanguage, code, context, argumentNames); } diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Tue Nov 10 19:42:37 2015 -0800 @@ -728,7 +728,7 @@ @Override public String getPath() { - return description; + return null; } @Override diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Tue Nov 10 19:42:37 2015 -0800 @@ -152,6 +152,7 @@ public SimpleREPLClient(REPLServer replServer) { this.replServer = replServer; + // TODO (mlvdv) language-dependent this.languageName = replServer.getLanguageName(); this.writer = System.out; try { @@ -258,18 +259,26 @@ this.level = predecessor == null ? 0 : predecessor.level + 1; if (message != null) { + final String sourceName = message.get(REPLMessage.SOURCE_NAME); try { - this.haltedSource = Source.fromFileName(message.get(REPLMessage.SOURCE_NAME)); - selectedSource = this.haltedSource; + this.haltedSource = Source.fromFileName(sourceName); + } catch (IOException ex) { + final String code = message.get(REPLMessage.SOURCE_TEXT); + if (code != null) { + this.haltedSource = Source.fromText(code, sourceName); + } + } + if (this.haltedSource != null) { + selectedSource = haltedSource; try { haltedLineNumber = Integer.parseInt(message.get(REPLMessage.LINE_NUMBER)); } catch (NumberFormatException e) { haltedLineNumber = 0; } - } catch (IOException e1) { + } else { this.haltedSource = null; this.haltedLineNumber = 0; - this.unknownSourceName = message.get(REPLMessage.SOURCE_NAME); + this.unknownSourceName = sourceName; } } updatePrompt(); diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Tue Nov 10 19:42:37 2015 -0800 @@ -44,6 +44,7 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.vm.PolyglotEngine.Language; import com.oracle.truffle.tools.debug.shell.REPLMessage; +import com.oracle.truffle.tools.debug.shell.server.REPLServer.Context; /** * Server-side REPL implementation of an {@linkplain REPLMessage "op"}. @@ -403,30 +404,19 @@ } }; public static final REPLHandler EVAL_HANDLER = new REPLHandler(REPLMessage.EVAL) { - @SuppressWarnings("unused") @Override public REPLMessage[] receive(REPLMessage request, REPLServer replServer) { final REPLMessage reply = createReply(); final String sourceName = request.get(REPLMessage.SOURCE_NAME); reply.put(REPLMessage.SOURCE_NAME, sourceName); - reply.put(REPLMessage.DEBUG_LEVEL, Integer.toString(replServer.getCurrentContext().getLevel())); + final Context serverContext = replServer.getCurrentContext(); + reply.put(REPLMessage.DEBUG_LEVEL, Integer.toString(serverContext.getLevel())); final String source = request.get(REPLMessage.CODE); final Visualizer visualizer = replServer.getVisualizer(); - final Integer frameNumber = request.getIntValue(REPLMessage.FRAME_NUMBER); - FrameInstance frameInstance = null; - if (frameNumber != null) { - final List stack = replServer.getCurrentContext().getStack(); - if (frameNumber < 0 || frameNumber >= stack.size()) { - return finishReplyFailed(reply, "invalid frame number"); - } - final FrameDebugDescription frameDescription = stack.get(frameNumber); - // frameInstance = frameDescription == null ? null : - // frameDescription.frameInstance(); - } try { - Object returnValue = replServer.getCurrentContext().eval(source, frameInstance); + Object returnValue = serverContext.eval(source, frameNumber); return finishReplySucceeded(reply, visualizer.displayValue(returnValue, 0)); } catch (QuitException ex) { throw ex; diff -r fa1061fb21fa -r ad180d3d4bd7 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Wed Nov 04 16:12:56 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Tue Nov 10 19:42:37 2015 -0800 @@ -71,6 +71,7 @@ private final Map handlerMap = new HashMap<>(); // TODO (mlvdv) Language-specific + private final String mimeType; private final PolyglotEngine.Language language; private final Visualizer visualizer; @@ -92,6 +93,7 @@ * Create a single-language server. */ public REPLServer(String mimeType, Visualizer visualizer) { + this.mimeType = mimeType; this.visualizer = visualizer == null ? new DefaultVisualizer() : visualizer; EventConsumer onHalted = new EventConsumer(SuspendedEvent.class) { @Override @@ -127,7 +129,9 @@ } } } - event.prepareStepInto(); + if (!currentServerContext.isEval) { + event.prepareStepInto(); + } } }; engine = PolyglotEngine.buildNew().onEvent(onHalted).onEvent(onExec).build(); @@ -147,13 +151,6 @@ */ public void start() { - addHandlers(); - this.replClient = new SimpleREPLClient(this); - this.currentServerContext = new Context(null, null); - replClient.start(); - } - - protected void addHandlers() { add(REPLHandler.BACKTRACE_HANDLER); add(REPLHandler.BREAK_AT_LINE_HANDLER); add(REPLHandler.BREAK_AT_LINE_ONCE_HANDLER); @@ -180,6 +177,9 @@ add(REPLHandler.TRUFFLE_HANDLER); add(REPLHandler.TRUFFLE_NODE_HANDLER); add(REPLHandler.UNSET_BREAK_CONDITION_HANDLER); + this.replClient = new SimpleREPLClient(this); + this.currentServerContext = new Context(null, null); + replClient.start(); } void haltedAt(SuspendedEvent event) { @@ -192,7 +192,12 @@ final SourceSection src = event.getNode().getSourceSection(); final Source source = src.getSource(); message.put(REPLMessage.SOURCE_NAME, source.getName()); - message.put(REPLMessage.FILE_PATH, source.getPath()); + final String path = source.getPath(); + if (path == null) { + message.put(REPLMessage.SOURCE_TEXT, source.getCode()); + } else { + message.put(REPLMessage.FILE_PATH, path); + } message.put(REPLMessage.LINE_NUMBER, Integer.toString(src.getStartLine())); message.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED); message.put(REPLMessage.DEBUG_LEVEL, Integer.toString(currentServerContext.getLevel())); @@ -224,6 +229,7 @@ private final Context predecessor; private final int level; private final SuspendedEvent event; + private boolean isEval = false; // When true, run without StepInto Context(Context predecessor, SuspendedEvent event) { this.level = predecessor == null ? 0 : predecessor.getLevel() + 1; @@ -246,19 +252,26 @@ } /** - * Evaluates given code snippet in the context of currently suspended execution. + * Evaluates a code snippet in the context of a selected frame in the currently suspended + * execution. * * @param code the snippet to evaluate - * @param frame null in case the evaluation should happen in top most frame, - * non-null value + * @param frameNumber index of the stack frame in which to evaluate, {@code null} if the + * topmost frame should be used. * @return result of the evaluation * @throws IOException if something goes wrong */ - Object eval(String code, FrameInstance frame) throws IOException { + Object eval(String code, Integer frameNumber) throws IOException { if (event == null) { - throw new IOException("top level \"eval\" not yet supported"); + try { + isEval = true; + final Value value = engine.eval(Source.fromText(code, "eval(\"" + code + "\")").withMimeType(mimeType)); + return value.get(); + } finally { + isEval = false; + } } - return event.eval(code, frame); + return event.eval(code, frameNumber); } /**