changeset 22451:ad180d3d4bd7

Merge with fa1061fb21fa5e69d4108201e9544d550a0fa036
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 10 Nov 2015 19:42:37 -0800
parents a8b796ac350d (diff) fa1061fb21fa (current diff)
children 163fdf64587d
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.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 7 files changed, 78 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- 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<? extends TruffleLanguage> 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
--- 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<FrameInstance> frames;
+    private final int stackSize;
     private final Debugger debugger;
 
     SuspendedEvent(Debugger prepares, Node astNode, MaterializedFrame mFrame, List<String> 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 <code>null</code> in case the evaluation should happen in top most frame,
+     * @param frameNumber <code>null</code> 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));
     }
 }
--- 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);
     }
--- 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
--- 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();
--- 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<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	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<String, REPLHandler> 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<SuspendedEvent> onHalted = new EventConsumer<SuspendedEvent>(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 <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);
         }
 
         /**