changeset 22447:a8b796ac350d

Truffle/REPL: upate to use new support for "eval"
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 10 Nov 2015 18:25:52 -0800
parents 5b6e15432aae
children ad180d3d4bd7
files truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java
diffstat 3 files changed, 46 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java	Tue Nov 10 18:25:30 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java	Tue Nov 10 18:25:52 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();
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Tue Nov 10 18:25:30 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Tue Nov 10 18:25:52 2015 -0800
@@ -43,6 +43,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<FrameDebugDescription> 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;
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Tue Nov 10 18:25:30 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Tue Nov 10 18:25:52 2015 -0800
@@ -68,6 +68,7 @@
     private final Map<String, REPLHandler> handlerMap = new HashMap<>();
 
     // TODO (mlvdv) Language-specific
+    private final String mimeType;
     private final PolyglotEngine.Language language;
     private final Visualizer visualizer;
 
@@ -79,6 +80,7 @@
      * Create a single-language server.
      */
     public REPLServer(String mimeType, Visualizer visualizer) {
+        this.mimeType = mimeType;
         this.visualizer = visualizer == null ? new DefaultVisualizer() : visualizer;
         EventConsumer<SuspendedEvent> onHalted = new EventConsumer<SuspendedEvent>(SuspendedEvent.class) {
             @Override
@@ -90,7 +92,9 @@
             @Override
             protected void on(ExecutionEvent event) {
                 db = event.getDebugger();
-                event.prepareStepInto();
+                if (!currentServerContext.isEval) {
+                    event.prepareStepInto();
+                }
             }
         };
         engine = PolyglotEngine.buildNew().onEvent(onHalted).onEvent(onExec).build();
@@ -110,13 +114,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);
@@ -143,6 +140,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) {
@@ -155,7 +155,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()));
@@ -187,6 +192,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;
@@ -209,19 +215,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 <code>null</code> 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);
         }
 
         /**
@@ -364,7 +377,7 @@
     void call(String name) throws IOException {
         Value symbol = engine.findGlobalSymbol(name);
         if (symbol == null) {
-            throw new IOException("symboleval f \"" + name + "\" not found");
+            throw new IOException("symbol \"" + name + "\" not found");
         }
         symbol.invoke(null);
     }