# HG changeset patch # User Michael Van De Vanter # Date 1448157233 28800 # Node ID 64658afaf9c0bb2e9bc1e9879eb6de25f937e53a # Parent 5573f12b94f8c4df81d26dde2637a7e66e8614f6 Truffle/REPL debugger: add "loads" and "evals" commands that "step into"; default is now not to step into diff -r 5573f12b94f8 -r 64658afaf9c0 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java Wed Nov 18 20:38:32 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java Sat Nov 21 17:53:53 2015 -0800 @@ -120,6 +120,7 @@ public static final String SUBTREE = "subtree"; public static final String SUCCEEDED = "succeeded"; public static final String TOPIC = "topic"; + public static final String TRUE = "true"; public static final String TRUFFLE = "truffle"; public static final String TRUFFLE_AST = "truffle-ast"; public static final String TRUFFLE_NODE = "truffle-node"; diff -r 5573f12b94f8 -r 64658afaf9c0 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java Wed Nov 18 20:38:32 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java Sat Nov 21 17:53:53 2015 -0800 @@ -229,6 +229,17 @@ } return request; } + + @Override + void processReply(REPLClientContext context, REPLMessage[] replies) { + REPLMessage firstReply = replies[0]; + if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) { + final String result = firstReply.get(REPLMessage.DISPLAY_MSG); + context.displayFailReply(result != null ? result : firstReply.toString()); + } else { + context.displayReply(firstReply.get(REPLMessage.VALUE)); + } + } }; public static final REPLRemoteCommand CLEAR_BREAK_CMD = new REPLRemoteCommand("clear", null, "Clear a breakpoint") { @@ -467,6 +478,59 @@ } }; + public static final REPLRemoteCommand EVAL_CMD = new REPLRemoteCommand("eval", null, "Evaluate a string, in context of the current frame if any") { + + private int evalCounter = 0; + + private final String[] help = {"eval : evaluate in context of the current frame if any"}; + + @Override + public String[] getHelp() { + return help; + } + + @Override + public REPLMessage createRequest(REPLClientContext context, String[] args) { + if (args.length > 1) { + final String code = args[1]; + if (!code.isEmpty()) { + // Create a fake entry in the file maps and cache, based on this unique name + final String fakeFileName = ""; + Source.fromNamedText(fakeFileName, code); + final REPLMessage request = new REPLMessage(); + request.put(REPLMessage.OP, REPLMessage.EVAL); + request.put(REPLMessage.CODE, code); + request.put(REPLMessage.SOURCE_NAME, fakeFileName); + if (context.level() > 0) { + // Specify a requested execution context, if one exists; otherwise top level + request.put(REPLMessage.FRAME_NUMBER, Integer.toString(context.getSelectedFrameNumber())); + } + return request; + } + } + return null; + } + }; + + public static final REPLRemoteCommand EVAL_STEP_INTO_CMD = new REPLRemoteCommand("eval-step-into", "evals", "Evaluate and step into a string, in context of the current frame if any") { + + private final String[] help = {"eval-step-into : evaluate in context of the current frame if any, and step into"}; + + @Override + public String[] getHelp() { + return help; + } + + @Override + public REPLMessage createRequest(REPLClientContext context, String[] args) { + final REPLMessage request = EVAL_CMD.createRequest(context, args); + if (request != null) { + request.put(REPLMessage.STEP_INTO, REPLMessage.TRUE); + } + return request; + } + }; + public static final REPLRemoteCommand FRAME_CMD = new REPLRemoteCommand("frame", null, "Display a stack frame") { private final String[] help = {"frame : display currently selected frame", "frame : display frame "}; @@ -545,6 +609,13 @@ public static final REPLRemoteCommand LOAD_CMD = new REPLRemoteCommand("load", null, "Load source") { + private final String[] help = new String[]{"load : load currently selected file source", "load : load file "}; + + @Override + public String[] getHelp() { + return help; + } + @Override public REPLMessage createRequest(REPLClientContext context, String[] args) { Source runSource = null; @@ -569,8 +640,34 @@ } }; + public static final REPLRemoteCommand LOAD_STEP_INTO_CMD = new REPLRemoteCommand("load-step-into", "loads", "Load source and step in") { + + private final String[] help = new String[]{"load : load currently selected file source and step in", "load : load file and step in"}; + + @Override + public String[] getHelp() { + return help; + } + + @Override + public REPLMessage createRequest(REPLClientContext context, String[] args) { + final REPLMessage request = LOAD_CMD.createRequest(context, args); + if (request != null) { + request.put(REPLMessage.STEP_INTO, REPLMessage.TRUE); + } + return request; + } + }; + public static final REPLRemoteCommand SET_LANG_CMD = new REPLRemoteCommand("language", "lang", "Set current language") { + private final String[] help = new String[]{"lang : set default language, \"info lang\" displays choices"}; + + @Override + public String[] getHelp() { + return help; + } + @Override public REPLMessage createRequest(REPLClientContext context, String[] args) { if (args.length == 1) { @@ -593,9 +690,11 @@ public static final REPLRemoteCommand STEP_INTO_CMD = new REPLRemoteCommand("step", "s", "(StepInto) next statement, going into functions.") { + private final String[] help = new String[]{"step into: step to next statement (into calls)", "step : step to nth next statement (into calls)"}; + @Override public String[] getHelp() { - return new String[]{"step into: step to next statement (into calls)", "step : step to nth next statement (into calls)"}; + return help; } @Override @@ -654,9 +753,12 @@ public static final REPLRemoteCommand STEP_OVER_CMD = new REPLRemoteCommand("next", "n", "(StepOver) execute next line of code, not into functions.") { + private final String[] help = new String[]{"next: (StepOver) execute next line of code, not into functions.", + "next : (StepOver) execute to nth next statement (not counting into functions)"}; + @Override public String[] getHelp() { - return new String[]{"next: (StepOver) execute next line of code, not into functions.", "next : (StepOver) execute to nth next statement (not counting into functions)"}; + return help; } @Override diff -r 5573f12b94f8 -r 64658afaf9c0 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 18 20:38:32 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Sat Nov 21 17:53:53 2015 -0800 @@ -165,7 +165,8 @@ addCommand(REPLRemoteCommand.DISABLE_CMD); addCommand(REPLRemoteCommand.DOWN_CMD); addCommand(REPLRemoteCommand.ENABLE_CMD); - addCommand(evalCommand); + addCommand(REPLRemoteCommand.EVAL_CMD); + addCommand(REPLRemoteCommand.EVAL_STEP_INTO_CMD); addCommand(fileCommand); addCommand(REPLRemoteCommand.FRAME_CMD); addCommand(helpCommand); @@ -173,6 +174,7 @@ addCommand(REPLRemoteCommand.KILL_CMD); addCommand(listCommand); addCommand(REPLRemoteCommand.LOAD_CMD); + addCommand(REPLRemoteCommand.LOAD_STEP_INTO_CMD); addCommand(quitCommand); addCommand(setCommand); addCommand(REPLRemoteCommand.SET_LANG_CMD); @@ -723,33 +725,6 @@ } }; - private final REPLCommand evalCommand = new REPLRemoteCommand("eval", null, "Evaluate a string, in context of the current frame if any") { - - private int evalCounter = 0; - - @Override - public REPLMessage createRequest(REPLClientContext context, String[] args) { - if (args.length > 1) { - final String code = args[1]; - if (!code.isEmpty()) { - // Create a fake entry in the file maps and cache, based on this unique name - final String fakeFileName = ""; - Source.fromNamedText(fakeFileName, code); - final REPLMessage request = new REPLMessage(); - request.put(REPLMessage.OP, REPLMessage.EVAL); - request.put(REPLMessage.CODE, code); - request.put(REPLMessage.SOURCE_NAME, fakeFileName); - if (clientContext.level > 0) { - // Specify a requested execution context, if one exists; otherwise top level - request.put(REPLMessage.FRAME_NUMBER, Integer.toString(context.getSelectedFrameNumber())); - } - return request; - } - } - return null; - } - }; - private final REPLCommand fileCommand = new REPLRemoteCommand("file", null, "Set/display current file for viewing") { final String[] help = {"file: display current file path", "file : Set file to be current file for viewing"}; diff -r 5573f12b94f8 -r 64658afaf9c0 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 18 20:38:32 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Sat Nov 21 17:53:53 2015 -0800 @@ -137,7 +137,7 @@ if (section == null) { section = node.getEncapsulatingSourceSection(); } - if (section != null) { + if (section != null && section.getSource() != null) { infoMessage.put(REPLMessage.FILE_PATH, section.getSource().getPath()); infoMessage.put(REPLMessage.LINE_NUMBER, Integer.toString(section.getStartLine())); infoMessage.put(REPLMessage.SOURCE_LINE_TEXT, section.getSource().getCode(section.getStartLine())); @@ -291,7 +291,7 @@ if (callName == null) { return finishReplyFailed(reply, "no name specified"); } - final ArrayList argList = new ArrayList<>(); + final ArrayList argList = new ArrayList<>(); for (int argCount = 0; argCount < REPLMessage.ARG_NAMES.length; argCount++) { final String arg = request.get(REPLMessage.ARG_NAMES[argCount]); if (arg == null) { @@ -299,9 +299,9 @@ } argList.add(arg); } - final Object[] args = argList.toArray(new Object[0]); try { - replServer.call(callName, args); + final Object result = replServer.call(callName, argList); + reply.put(REPLMessage.VALUE, result == null ? "" : result.toString()); } catch (QuitException ex) { throw ex; } catch (KillException ex) { @@ -407,8 +407,9 @@ final String source = request.get(REPLMessage.CODE); final Visualizer visualizer = replServer.getVisualizer(); final Integer frameNumber = request.getIntValue(REPLMessage.FRAME_NUMBER); + final boolean stepInto = REPLMessage.TRUE.equals(request.get(REPLMessage.STEP_INTO)); try { - Object returnValue = serverContext.eval(source, frameNumber); + Object returnValue = serverContext.eval(source, frameNumber, stepInto); return finishReplySucceeded(reply, visualizer.displayValue(returnValue, 0)); } catch (QuitException ex) { throw ex; @@ -549,11 +550,10 @@ public REPLMessage[] receive(REPLMessage request, REPLServer replServer) { final REPLMessage reply = new REPLMessage(REPLMessage.OP, REPLMessage.LOAD_SOURCE); final String fileName = request.get(REPLMessage.SOURCE_NAME); + final boolean stepInto = REPLMessage.TRUE.equals(request.get(REPLMessage.STEP_INTO)); try { final Source fileSource = Source.fromFileName(fileName); - // TODO (mlvdv) language-specific - assert replServer.getLanguage().getMimeTypes().contains(fileSource.getMimeType()); - replServer.eval(fileSource); + replServer.getCurrentContext().eval(fileSource, stepInto); reply.put(REPLMessage.FILE_PATH, fileName); return finishReplySucceeded(reply, fileName + " loaded"); } catch (QuitException ex) { diff -r 5573f12b94f8 -r 64658afaf9c0 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 18 20:38:32 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Sat Nov 21 17:53:53 2015 -0800 @@ -159,7 +159,7 @@ } } } - if (!currentServerContext.isEval) { + if (currentServerContext.steppingInto) { event.prepareStepInto(); } } @@ -289,7 +289,7 @@ private final int level; private final SuspendedEvent event; private Language currentLanguage; - private boolean isEval = false; // When true, run without StepInto + private boolean steppingInto = false; // Only true during a "stepInto" engine call Context(Context predecessor, SuspendedEvent event, Language language) { assert language != null; @@ -313,6 +313,15 @@ return event.getNode(); } + void eval(Source source, boolean stepInto) throws IOException { + this.steppingInto = stepInto; + try { + engine.eval(source); + } finally { + this.steppingInto = false; + } + } + /** * Evaluates a code snippet in the context of a selected frame in the currently suspended * execution. @@ -323,18 +332,26 @@ * @return result of the evaluation * @throws IOException if something goes wrong */ - Object eval(String code, Integer frameNumber) throws IOException { + Object eval(String code, Integer frameNumber, boolean stepInto) throws IOException { if (event == null) { + this.steppingInto = stepInto; + final String mimeType = defaultMIME(currentLanguage); try { - isEval = true; - final String mimeType = defaultMIME(currentLanguage); - final Value value = engine.eval(Source.fromText(code, "eval(\"" + code + "\")").withMimeType(mimeType)); - return value.get(); + return engine.eval(Source.fromText(code, "eval(\"" + code + "\")").withMimeType(mimeType)).get(); } finally { - isEval = false; + this.steppingInto = false; + } + } else { + if (stepInto) { + event.prepareStepInto(1); + } + try { + final Object result = event.eval(code, frameNumber); + return (result instanceof Value) ? ((Value) result).get() : result; + } finally { + event.prepareContinue(); } } - return event.eval(code, frameNumber); } /** @@ -462,10 +479,6 @@ return language.getMimeTypes().iterator().next(); } - void eval(Source source) throws IOException { - engine.eval(source); - } - Breakpoint setLineBreakpoint(int ignoreCount, LineLocation lineLocation, boolean oneShot) throws IOException { Breakpoint breakpoint; if (db == null) { @@ -518,12 +531,22 @@ breakpoints.remove(breakpoint); } - void call(String name, Object... args) throws IOException { + Object call(String name, List argList) throws IOException { Value symbol = engine.findGlobalSymbol(name); if (symbol == null) { throw new IOException("symbol \"" + name + "\" not found"); } - symbol.invoke(null, args); + final List args = new ArrayList<>(); + for (String stringArg : argList) { + Integer intArg = null; + try { + intArg = Integer.valueOf(stringArg); + args.add(intArg); + } catch (NumberFormatException e) { + args.add(stringArg); + } + } + return symbol.invoke(null, args.toArray(new Object[0])).get(); } /**