comparison graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java @ 21568:3b8bbf51d320

Truffle/Debugging: add the Truffle DebugEngine and supporting code, as well as add a crude command-line debugging tool used mainly to test the DebugEngine. Migrate the small tols out of project com.oracle.truffle.api into the new project com.oracle.truffle.tools.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 26 May 2015 16:38:13 -0700
parents
children
comparison
equal deleted inserted replaced
21470:1bbef57f9a38 21568:3b8bbf51d320
1 /*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package com.oracle.truffle.tools.debug.shell.client;
26
27 import java.io.*;
28 import java.util.*;
29
30 import com.oracle.truffle.api.source.*;
31 import com.oracle.truffle.tools.debug.shell.*;
32
33 // TODO (mlvdv) write a real command line parser
34 public abstract class REPLRemoteCommand extends REPLCommand {
35
36 public REPLRemoteCommand(String command, String abbreviation, String description) {
37 super(command, abbreviation, description);
38 }
39
40 protected abstract REPLMessage createRequest(REPLClientContext context, String[] args);
41
42 void processReply(REPLClientContext context, REPLMessage[] replies) {
43 REPLMessage firstReply = replies[0];
44
45 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
46 final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
47 context.displayFailReply(result != null ? result : firstReply.toString());
48 } else {
49 final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
50 context.displayReply(result != null ? result : firstReply.toString());
51 }
52
53 for (int i = 1; i < replies.length; i++) {
54 REPLMessage reply = replies[i];
55 final String result = reply.get(REPLMessage.DISPLAY_MSG);
56 context.displayInfo(result != null ? result : reply.toString());
57 }
58 }
59
60 public static final REPLRemoteCommand BREAK_AT_LINE_CMD = new REPLRemoteCommand("break-at-line", "break", "Set a breakpoint") {
61
62 private final String[] help = {"break <n> [ignore=<n>] : set breakpoint at line <n> in current file", "break <filename>:<n> [ignore=<n>] : set breakpoint at line <n> in <filename>",
63 " optionally ignore first <n> hits (default 0)"};
64
65 @Override
66 public String[] getHelp() {
67 return help;
68 }
69
70 @Override
71 public REPLMessage createRequest(REPLClientContext context, String[] args) {
72 try {
73 final REPLineLocation lineLocation = REPLineLocation.parse(context, args);
74 final REPLMessage requestMessage = lineLocation.createMessage(REPLMessage.BREAK_AT_LINE);
75 int ignoreCount = 0;
76 if (args.length > 2) {
77 final String ignoreText = args[2];
78 if (ignoreText.equals("ignore")) {
79 throw new IllegalArgumentException("No ignore count specified");
80 }
81 final String[] split = ignoreText.split("=");
82 if (split.length == 2 && split[0].equals("ignore")) {
83 try {
84 ignoreCount = Integer.parseInt(split[1]);
85 if (ignoreCount < 0) {
86 throw new IllegalArgumentException("Illegal ignore count: " + split[1]);
87 }
88 } catch (NumberFormatException e) {
89 throw new IllegalArgumentException("No ignore count specified");
90 }
91 } else {
92 throw new IllegalArgumentException("Unrecognized argument \"" + ignoreText + "\"");
93 }
94 }
95 requestMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(ignoreCount));
96 return requestMessage;
97 } catch (IllegalArgumentException ex) {
98 context.displayFailReply(ex.getMessage());
99 }
100 return null;
101 }
102
103 @Override
104 void processReply(REPLClientContext context, REPLMessage[] replies) {
105 REPLMessage firstReply = replies[0];
106
107 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
108 final String number = firstReply.get(REPLMessage.BREAKPOINT_ID);
109 final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
110 final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
111 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + number + " set at " + fileName + ":" + lineNumber);
112 }
113 super.processReply(context, replies);
114 }
115 };
116
117 public static final REPLRemoteCommand BREAK_AT_LINE_ONCE_CMD = new REPLRemoteCommand("break-at-line-once", "break1", "Set a one-shot breakpoint") {
118
119 private final String[] help = {"break <n>: set one-shot breakpoint at line <n> in current file", "break <filename>:<n>: set one-shot breakpoint at line <n> in current file"};
120
121 @Override
122 public String[] getHelp() {
123 return help;
124 }
125
126 @Override
127 public REPLMessage createRequest(REPLClientContext context, String[] args) {
128 try {
129 return REPLineLocation.parse(context, args).createMessage(REPLMessage.BREAK_AT_LINE_ONCE);
130 } catch (IllegalArgumentException ex) {
131 context.displayFailReply(ex.getMessage());
132 }
133 return null;
134 }
135
136 @Override
137 void processReply(REPLClientContext context, REPLMessage[] replies) {
138 REPLMessage firstReply = replies[0];
139
140 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
141 final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
142 final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
143 firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint set at " + fileName + ":" + lineNumber);
144 }
145 super.processReply(context, replies);
146 }
147 };
148
149 public static final REPLRemoteCommand BREAK_AT_THROW_CMD = new REPLRemoteCommand("break-at-throw", "breakthrow", "Break at any throw") {
150
151 private final String[] help = {"break-at-throw: set breakpoint on any throw"};
152
153 @Override
154 public String[] getHelp() {
155 return help;
156 }
157
158 @Override
159 public REPLMessage createRequest(REPLClientContext context, String[] args) {
160 final REPLMessage request = new REPLMessage();
161 request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW);
162 return request;
163 }
164
165 @Override
166 void processReply(REPLClientContext context, REPLMessage[] replies) {
167 REPLMessage firstReply = replies[0];
168
169 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
170 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint at any throw set");
171 }
172 super.processReply(context, replies);
173 }
174 };
175
176 public static final REPLRemoteCommand BREAK_AT_THROW_ONCE_CMD = new REPLRemoteCommand("break-at-throw-once", "break1throw", "Break once at any throw") {
177
178 private final String[] help = {"break-at-throw: set one-short breakpoint on any throw"};
179
180 @Override
181 public String[] getHelp() {
182 return help;
183 }
184
185 @Override
186 public REPLMessage createRequest(REPLClientContext context, String[] args) {
187 final REPLMessage request = new REPLMessage();
188 request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW_ONCE);
189 return request;
190 }
191
192 @Override
193 void processReply(REPLClientContext context, REPLMessage[] replies) {
194 REPLMessage firstReply = replies[0];
195
196 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
197 firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint at any throw set");
198 }
199 super.processReply(context, replies);
200 }
201 };
202
203 public static final REPLRemoteCommand CLEAR_BREAK_CMD = new REPLRemoteCommand("clear", null, "Clear a breakpoint") {
204
205 private final String[] help = {"clear <n>: clear breakpoint number <n>"};
206
207 @Override
208 public String[] getHelp() {
209 return help;
210 }
211
212 @Override
213 public REPLMessage createRequest(REPLClientContext context, String[] args) {
214 if (args.length == 1) {
215 context.displayFailReply("breakpoint number not speciified: \"break <n>\"");
216 } else if (args.length > 2) {
217 context.displayFailReply("breakpoint number not understood: \"break <n>\"");
218 } else {
219 try {
220 final int breakpointNumber = Integer.parseInt(args[1]);
221 final REPLMessage request = new REPLMessage();
222 request.put(REPLMessage.OP, REPLMessage.CLEAR_BREAK);
223 request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
224 return request;
225 } catch (IllegalArgumentException ex) {
226 context.displayFailReply(ex.getMessage());
227 }
228 }
229 return null;
230 }
231
232 @Override
233 void processReply(REPLClientContext context, REPLMessage[] replies) {
234 REPLMessage firstReply = replies[0];
235
236 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
237 final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
238 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " cleared");
239 }
240 super.processReply(context, replies);
241 }
242 };
243
244 public static final REPLRemoteCommand CONDITION_BREAK_CMD = new REPLRemoteCommand("cond", null, "Set new condition on a breakpoint") {
245
246 private final String[] help = {"cond <n> [expr]: sets new condition on breakpoint number <n>; make unconditional if no [expr]"};
247
248 @Override
249 public String[] getHelp() {
250 return help;
251 }
252
253 @Override
254 public REPLMessage createRequest(REPLClientContext context, String[] args) {
255 if (args.length == 1) {
256 context.displayFailReply("breakpoint number not speciified: \"cond <n>\"");
257 } else {
258 try {
259 final int breakpointNumber = Integer.parseInt(args[1]);
260 final REPLMessage request = new REPLMessage();
261 request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
262 if (args.length == 2) {
263 request.put(REPLMessage.OP, REPLMessage.UNSET_BREAK_CONDITION);
264 } else {
265 final StringBuilder exprBuilder = new StringBuilder();
266 for (int i = 2; i < args.length; i++) {
267 exprBuilder.append(args[i]).append(" ");
268 }
269 request.put(REPLMessage.BREAKPOINT_CONDITION, exprBuilder.toString().trim());
270 request.put(REPLMessage.OP, REPLMessage.SET_BREAK_CONDITION);
271 }
272 return request;
273 } catch (IllegalArgumentException ex) {
274 context.displayFailReply(ex.getMessage());
275 }
276 }
277 return null;
278 }
279
280 @Override
281 void processReply(REPLClientContext context, REPLMessage[] replies) {
282 REPLMessage firstReply = replies[0];
283 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
284 final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
285 final String condition = firstReply.get(REPLMessage.BREAKPOINT_CONDITION);
286 if (condition == null) {
287 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition cleared");
288 } else {
289 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition=\"" + condition + "\"");
290 }
291 }
292 super.processReply(context, replies);
293 }
294 };
295
296 public static final REPLRemoteCommand CONTINUE_CMD = new REPLRemoteCommand("continue", "c", "Continue execution") {
297
298 @Override
299 public REPLMessage createRequest(REPLClientContext context, String[] args) {
300 if (context.level() == 0) {
301 context.displayFailReply("no active execution");
302 return null;
303 }
304 final REPLMessage request = new REPLMessage();
305 request.put(REPLMessage.OP, REPLMessage.CONTINUE);
306 return request;
307 }
308
309 @Override
310 void processReply(REPLClientContext context, REPLMessage[] replies) {
311
312 throw new REPLContinueException();
313
314 }
315 };
316
317 public static final REPLRemoteCommand DELETE_CMD = new REPLRemoteCommand("delete", "d", "Delete all breakpoints") {
318
319 @Override
320 public REPLMessage createRequest(REPLClientContext context, String[] args) {
321 final REPLMessage request = new REPLMessage();
322 request.put(REPLMessage.OP, REPLMessage.DELETE_BREAK);
323 return request;
324 }
325 };
326
327 public static final REPLRemoteCommand DISABLE_CMD = new REPLRemoteCommand("disable", null, "Disable a breakpoint") {
328
329 private final String[] help = {"disable <n>: disable breakpoint number <n>"};
330
331 @Override
332 public String[] getHelp() {
333 return help;
334 }
335
336 @Override
337 public REPLMessage createRequest(REPLClientContext context, String[] args) {
338 if (args.length == 1) {
339 context.displayFailReply("breakpoint number not speciified: \"disable <n>\"");
340 } else if (args.length > 2) {
341 context.displayFailReply("breakpoint number not understood: \"disable <n>\"");
342 } else {
343 try {
344 final int breakpointNumber = Integer.parseInt(args[1]);
345 final REPLMessage request = new REPLMessage();
346 request.put(REPLMessage.OP, REPLMessage.DISABLE_BREAK);
347 request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
348 return request;
349 } catch (IllegalArgumentException ex) {
350 context.displayFailReply(ex.getMessage());
351 }
352 }
353 return null;
354 }
355
356 @Override
357 void processReply(REPLClientContext context, REPLMessage[] replies) {
358 REPLMessage firstReply = replies[0];
359 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
360 final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
361 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " disabled");
362 }
363 super.processReply(context, replies);
364 }
365 };
366
367 public static final REPLRemoteCommand DOWN_CMD = new REPLRemoteCommand("down", null, "Move down a stack frame") {
368
369 @Override
370 public REPLMessage createRequest(REPLClientContext context, String[] args) {
371 if (context.level() == 0) {
372 context.displayFailReply("no active execution");
373 return null;
374 }
375 final List<REPLFrame> frames = context.frames();
376 final int newFrameSelection = context.getSelectedFrameNumber() + 1;
377 if (newFrameSelection > frames.size() - 1) {
378 context.displayFailReply("at bottom of stack");
379 return null;
380 }
381 context.selectFrameNumber(newFrameSelection);
382 return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
383 }
384
385 @Override
386 void processReply(REPLClientContext context, REPLMessage[] replies) {
387 REPLMessage firstReply = replies[0];
388
389 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
390 final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
391 context.displayFailReply(result != null ? result : firstReply.toString());
392 } else {
393 context.displayStack();
394 }
395 }
396 };
397
398 public static final REPLRemoteCommand ENABLE_CMD = new REPLRemoteCommand("enable", null, "Enable a breakpoint") {
399
400 private final String[] help = {"enable <n>: enable breakpoint number <n>"};
401
402 @Override
403 public String[] getHelp() {
404 return help;
405 }
406
407 @Override
408 public REPLMessage createRequest(REPLClientContext context, String[] args) {
409 if (args.length == 1) {
410 context.displayFailReply("breakpoint number not speciified: \"enable <n>\"");
411 } else if (args.length > 2) {
412 context.displayFailReply("breakpoint number not understood: \"enable <n>\"");
413 } else {
414 try {
415 final int breakpointNumber = Integer.parseInt(args[1]);
416 final REPLMessage request = new REPLMessage();
417 request.put(REPLMessage.OP, REPLMessage.ENABLE_BREAK);
418 request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
419 return request;
420 } catch (IllegalArgumentException ex) {
421 context.displayFailReply(ex.getMessage());
422 }
423 }
424 return null;
425 }
426
427 @Override
428 void processReply(REPLClientContext context, REPLMessage[] replies) {
429 REPLMessage firstReply = replies[0];
430
431 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
432 final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
433 firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " enabled");
434 }
435 super.processReply(context, replies);
436 }
437 };
438
439 public static final REPLRemoteCommand FRAME_CMD = new REPLRemoteCommand("frame", null, "Display a stack frame") {
440
441 private final String[] help = {"frame : display currently selected frame", "frame <n> : display frame <n>"};
442
443 @Override
444 public String[] getHelp() {
445 return help;
446 }
447
448 @Override
449 public REPLMessage createRequest(REPLClientContext context, String[] args) {
450 if (context.level() == 0) {
451 context.displayFailReply("no active execution");
452 return null;
453 }
454 final REPLMessage request = new REPLMessage();
455 request.put(REPLMessage.OP, REPLMessage.FRAME);
456
457 int frameNumber = context.getSelectedFrameNumber();
458 if (args.length > 1) {
459 if (args.length == 2) {
460 try {
461 frameNumber = Integer.parseInt(args[1]);
462 } catch (NumberFormatException e) {
463 throw new IllegalArgumentException("Unrecognized argument \"" + args[1] + "\"");
464 }
465 } else {
466 throw new IllegalArgumentException("Unrecognized argument \"" + args[2] + "\"");
467 }
468 }
469 request.put(REPLMessage.FRAME_NUMBER, Integer.toString(frameNumber));
470 return request;
471 }
472
473 @Override
474 void processReply(REPLClientContext context, REPLMessage[] replies) {
475 if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
476 context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
477 } else {
478 Integer frameNumber = replies[0].getIntValue(REPLMessage.FRAME_NUMBER);
479 context.selectFrameNumber(frameNumber);
480 context.displayReply("Frame " + frameNumber + ":");
481 for (REPLMessage message : replies) {
482 for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
483 context.displayInfo(line);
484 }
485 }
486 }
487 }
488 };
489
490 public static final REPLRemoteCommand KILL_CMD = new REPLRemoteCommand("kill", null, "Stop program execution") {
491
492 @Override
493 public REPLMessage createRequest(REPLClientContext context, String[] args) {
494 if (context.level() == 0) {
495 context.displayFailReply("no active execution");
496 return null;
497 }
498 final REPLMessage request = new REPLMessage();
499 request.put(REPLMessage.OP, "kill");
500 return request;
501 }
502
503 @Override
504 void processReply(REPLClientContext context, REPLMessage[] replies) {
505 if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
506 context.displayReply(replies[0].get(REPLMessage.DISPLAY_MSG));
507 } else {
508 context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
509 }
510 }
511 };
512
513 public static final REPLRemoteCommand LOAD_RUN_CMD = new REPLRemoteCommand("load-run", "loadr", "Load and run a source") {
514
515 @Override
516 public REPLMessage createRequest(REPLClientContext context, String[] args) {
517 Source runSource = null;
518 if (args.length == 1) {
519 runSource = context.getSelectedSource();
520 if (runSource == null) {
521 context.displayFailReply("No file selected");
522 return null;
523 }
524 } else {
525 try {
526 runSource = Source.fromFileName(args[1]);
527 } catch (IOException e) {
528 context.displayFailReply("Can't find file: " + args[1]);
529 return null;
530 }
531 }
532 final REPLMessage request = new REPLMessage();
533 request.put(REPLMessage.OP, REPLMessage.LOAD_RUN);
534 request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
535 return request;
536 }
537 };
538
539 public static final REPLRemoteCommand LOAD_STEP_CMD = new REPLRemoteCommand("load-step", "loads", "Load and step into a source") {
540
541 @Override
542 public REPLMessage createRequest(REPLClientContext context, String[] args) {
543 Source runSource = null;
544 if (args.length == 1) {
545 runSource = context.getSelectedSource();
546 if (runSource == null) {
547 context.displayFailReply("No file selected");
548 return null;
549 }
550 } else {
551 try {
552 runSource = Source.fromFileName(args[1]);
553 } catch (IOException e) {
554 context.displayFailReply("Can't find file: " + args[1]);
555 return null;
556 }
557 }
558 final REPLMessage request = new REPLMessage();
559 request.put(REPLMessage.OP, REPLMessage.LOAD_STEP);
560 request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
561 return request;
562 }
563 };
564
565 public static final REPLRemoteCommand STEP_INTO_CMD = new REPLRemoteCommand("step", "s", "(StepInto) next statement, going into functions.") {
566
567 @Override
568 public String[] getHelp() {
569 return new String[]{"step into: step to next statement (into calls)", "step <n>: step to nth next statement (into calls)"};
570 }
571
572 @Override
573 public REPLMessage createRequest(REPLClientContext context, String[] args) {
574 if (context.level() == 0) {
575 context.displayFailReply("no active execution");
576 return null;
577 }
578 final REPLMessage request = new REPLMessage();
579 request.put(REPLMessage.OP, REPLMessage.STEP_INTO);
580
581 if (args.length >= 2) {
582 final String nText = args[1];
583 try {
584 final int nSteps = Integer.parseInt(nText);
585 if (nSteps > 0) {
586 request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
587 } else {
588 return null;
589 }
590 } catch (NumberFormatException e) {
591 context.displayFailReply("Step into count \"" + nText + "\" not recognized");
592 return null;
593 }
594 }
595 return request;
596 }
597
598 @Override
599 void processReply(REPLClientContext context, REPLMessage[] replies) {
600
601 throw new REPLContinueException();
602 }
603 };
604
605 public static final REPLRemoteCommand STEP_OUT_CMD = new REPLRemoteCommand("finish", null, "(StepOut) continue to end of function") {
606
607 @Override
608 public REPLMessage createRequest(REPLClientContext context, String[] args) {
609 if (context.level() == 0) {
610 context.displayFailReply("no active execution");
611 return null;
612 }
613 final REPLMessage request = new REPLMessage();
614 request.put(REPLMessage.OP, REPLMessage.STEP_OUT);
615
616 return request;
617 }
618
619 @Override
620 void processReply(REPLClientContext context, REPLMessage[] replies) {
621
622 throw new REPLContinueException();
623 }
624 };
625
626 public static final REPLRemoteCommand STEP_OVER_CMD = new REPLRemoteCommand("next", "n", "(StepOver) execute next line of code, not into functions.") {
627
628 @Override
629 public String[] getHelp() {
630 return new String[]{"next: (StepOver) execute next line of code, not into functions.", "next <n>: (StepOver) execute to nth next statement (not counting into functions)"};
631 }
632
633 @Override
634 public REPLMessage createRequest(REPLClientContext context, String[] args) {
635 if (context.level() == 0) {
636 context.displayFailReply("no active execution");
637 return null;
638 }
639 final REPLMessage request = new REPLMessage();
640 request.put(REPLMessage.OP, REPLMessage.STEP_OVER);
641
642 if (args.length >= 2) {
643 final String nText = args[1];
644 try {
645 final int nSteps = Integer.parseInt(nText);
646 if (nSteps > 0) {
647 request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
648 } else {
649 return null;
650 }
651 } catch (NumberFormatException e) {
652 context.displayFailReply("Next count \"" + nText + "\" not recognized");
653 return null;
654 }
655 }
656 return request;
657 }
658
659 @Override
660 void processReply(REPLClientContext context, REPLMessage[] replies) {
661
662 throw new REPLContinueException();
663 }
664 };
665
666 public static final REPLRemoteCommand UP_CMD = new REPLRemoteCommand("up", null, "Move up a stack frame") {
667
668 @Override
669 public REPLMessage createRequest(REPLClientContext context, String[] args) {
670 if (context.level() == 0) {
671 context.displayFailReply("no active execution");
672 return null;
673 }
674 final int newFrameSelection = context.getSelectedFrameNumber() - 1;
675 if (newFrameSelection < 0) {
676 context.displayFailReply("at top of stack");
677 return null;
678 }
679 context.selectFrameNumber(newFrameSelection);
680 return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
681 }
682
683 @Override
684 void processReply(REPLClientContext context, REPLMessage[] replies) {
685 REPLMessage firstReply = replies[0];
686
687 if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
688 final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
689 context.displayFailReply(result != null ? result : firstReply.toString());
690 } else {
691 context.displayStack();
692 }
693 }
694 };
695
696 }