Anonymous avatar Anonymous committed 8b7fdae

Refactored debugger to use custom SwankDebugInfo structure instead of LispNode returned by swank.

Comments (0)

Files changed (7)

src/org/lispdev/swank/ISwank.java

  */
 public interface ISwank
 {
+  LispImplementation getLispImplementation();
   /**
    * connect to a swank server
    */

src/org/lispdev/swank/LispImplementation.java

 
 import java.io.IOException;
 
+import org.lispdev.log.Log;
+
 /**
  * Abstract Lisp Implementation class.
  *
   {
     return filePath;
   }
+
+  /**
+   * Converts debugInfo node to corresponding structure.
+   * Debug info node is assumed to be of the following form:
+   * (:debug 0 1 ("break" " [condition]") (("RESTART1" "restart 1")
+   *   ("RESTART2" "restart 2")) ((0 "(frame 0)") (1 "frame 1")))
+   */
+  public SwankDebugInfo getDebugInfo(LispNode debugInfo)
+  {
+    if( debugInfo == null || !debugInfo.get(0).value.equals(":debug")
+        || debugInfo.getParamsCount() < 6
+        || debugInfo.get(3).getParamsCount() < 2 )
+    {
+      Log.logError("Debug info does not have correct structure: "+
+          String.valueOf(debugInfo));
+      return null;
+    }
+    SwankDebugInfo res = new SwankDebugInfo(debugInfo.get(1).value,
+        debugInfo.get(2).asInt(),
+        debugInfo.get(3).get(0) + "\n" + debugInfo.get(3).get(1));
+    if( res.condition == null || res.thread == null )
+    {
+      Log.logError("Debug info does not have correct structure: "+
+          String.valueOf(debugInfo));
+      return null;
+    }
+    for( LispNode ln : debugInfo.get(4).getParams() )
+    {
+      if( ln.getParamsCount() != 2 )
+      {
+        Log.logError("Debug info does not have correct structure: "+
+            String.valueOf(debugInfo));
+        return null;
+      }
+      res.addRestart(ln.get(0).value, ln.get(1).value);
+    }
+    for( LispNode ln : debugInfo.get(5).getParams() )
+    {
+      if( ln.getParamsCount() != 2 )
+      {
+        Log.logError("Debug info does not have correct structure: "+
+            String.valueOf(debugInfo));
+        return null;
+      }
+      res.addFrame(ln.get(1).value);
+    }
+    return res;
+  }
 }

src/org/lispdev/swank/LispProcess.java

   @Override
   public void terminate() throws DebugException
   {
+    fSwank.disconnect();
   }
 
   public ISwank getSwank()

src/org/lispdev/swank/LispThread.java

 package org.lispdev.swank;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
+import org.lispdev.swank.SwankDebugInfo.SwankDebugRestart;
 
 public class LispThread extends LispDebugElement implements IThread
 {
   private boolean suspended;
-  private LispNode debugInfo = null;
+  private SwankDebugInfo debugInfo = null;
 
   public LispThread(LispDebugTarget target)
   {
     return 0;
   }
 
-  public LispNode getRestarts()
+  public String getThreadID()
   {
     if( isSuspended() && debugInfo != null )
     {
-      return debugInfo.get(4);
+      return debugInfo.thread;
     }
     return null;
   }
 
-  public String getThreadID()
+  public int getDebugLevel()
   {
     if( isSuspended() && debugInfo != null )
     {
-      return debugInfo.get(1).value;
+      return debugInfo.level;
     }
-    return null;
+    return -1;
   }
 
-  public String getDebugLevel()
+  public List<SwankDebugRestart> getRestarts()
   {
     if( isSuspended() && debugInfo != null )
     {
-      return debugInfo.get(2).value;
+      return debugInfo.restarts;
     }
-    return null;
+    else
+    {
+      return new ArrayList<SwankDebugRestart>();
+    }
   }
 
   @Override
   {
     if( isSuspended() && debugInfo != null )
     {
-      LispNode backtrace = debugInfo.get(5);
-      if( backtrace != null )
+      IStackFrame[] res = new IStackFrame[debugInfo.frames.size()];
+      for( int i = 0; i < res.length; ++i )
       {
-        IStackFrame[] res = new IStackFrame[backtrace.getParamsCount()];
-        for( int i = 0; i < res.length; ++i )
-        {
-          res[i] = new LispStackFrame(this, backtrace.get(i).toString());
-        }
-        return res;
+        res[i] = new LispStackFrame(this, debugInfo.frames.get(i));
       }
-
+      return res;
     }
     return new IStackFrame[0];
   }
   {
   }
 
-  public void setSuspended(LispNode info)
+  public void setSuspended(SwankDebugInfo info)
   {
     debugInfo = info;
     suspended = (info != null);

src/org/lispdev/swank/SwankDebugInfo.java

+package org.lispdev.swank;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SwankDebugInfo
+{
+  public final String thread;
+  public final int level;
+  /**
+   * the condition to debug
+   */
+  public final String condition;
+  public final List<SwankDebugRestart> restarts =
+    new ArrayList<SwankDebugRestart>();
+  public final List<String> frames = new ArrayList<String>();
+
+  public SwankDebugInfo(String thread, int lvl, String condition)
+  {
+    this.thread = thread;
+    level = lvl;
+    this.condition = condition;
+  }
+
+  public void addRestart(String name, String description)
+  {
+    restarts.add(new SwankDebugRestart(capitalizeString(name), description));
+  }
+
+  private static String capitalizeString(String string)
+  {
+    char[] chars = string.toLowerCase().toCharArray();
+    boolean found = false;
+    for(int i = 0; i < chars.length; i++)
+    {
+      if( !found && Character.isLetter(chars[i]) )
+      {
+        chars[i] = Character.toUpperCase(chars[i]);
+        found = true;
+      }
+      else if( Character.isWhitespace(chars[i]) || chars[i] == '-' )
+      { // You can add other chars here
+        found = false;
+      }
+    }
+    return String.valueOf(chars);
+  }
+
+  public void addFrame(String frame)
+  {
+    frames.add(frame);
+  }
+
+  public static class SwankDebugRestart
+  {
+    public final String name;
+    public final String description;
+
+    public SwankDebugRestart(String name, String description)
+    {
+      this.name = name;
+      this.description = description;
+    }
+  }
+
+  @Override
+  public int hashCode()
+  {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((condition == null) ? 0 : condition.hashCode());
+    result = prime * result + level;
+    result = prime * result + ((thread == null) ? 0 : thread.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if( this == obj ) return true;
+    if( obj == null ) return false;
+    if( getClass() != obj.getClass() ) return false;
+    SwankDebugInfo other = (SwankDebugInfo)obj;
+    if( condition == null )
+    {
+      if( other.condition != null ) return false;
+    }
+    else if( !condition.equals(other.condition) ) return false;
+    if( level != other.level ) return false;
+    if( thread == null )
+    {
+      if( other.thread != null ) return false;
+    }
+    else if( !thread.equals(other.thread) ) return false;
+    return true;
+  }
+
+
+}

src/org/lispdev/swank/SwankInterface.java

 import java.util.ArrayList;
 import java.util.Hashtable;
 
+import org.eclipse.core.runtime.Assert;
+
 /*
  * C:\sbcl\bin\sbcl.exe --load "C:/slime/swank-loader.lisp" --eval
  * "(swank:create-swank-server 4005 nil)"
  */
 public class SwankInterface implements ISwank
 {
+  private final LispImplementation implementation;
+
   public SwankInterface(String extDir, LispImplementation implem,
       IRunnableDriver r)
   {
+    Assert.isNotNull(implem);
     this.extDir = extDir;
-    swank = new SwankInterfaceCore(r, implem,
-        (implem == null?-1:implem.getPort()));
+    swank = new SwankInterfaceCore(r, implem, implem.getPort());
+    implementation = implem;
+  }
+
+  @Override
+  public LispImplementation getLispImplementation()
+  {
+    return implementation;
   }
 
   protected final SwankInterfaceCore swank;

src/org/lispdev/swank/SwankInterfaceCore.java

       try
       {
         final String tag = node.car().value;
+//        if( tag.equals(":ping") )
+//        {
+//          sendRaw("(:emacs-pong " + node.get(1).value + " "
+//              + node.get(2).value + ")");
+//        }
+//        else if( tag.equals(":debug-activate")) //debugger is activated
+//        {
+//          signalListeners(node, SwankEvent.DEBUG_ACTIVATE);
+//        }
+//        else if( tag.equals(":debug")) //Event with debug info, usually right before a :debug-activate.
+//        {
+//          signalListeners(node, SwankEvent.DEBUG);
+//        }
+//        else if( tag.equals(":debug-return")) //the debugger is dismissed
+//        {
+//          signalListeners(node, SwankEvent.DEBUG_RETURN);
+//        }
+//        else if( tag.equals(":read-string")) //Lisp is trying to read something from the user
+//        {
+//          signalListeners(node, SwankEvent.READ_STRING);
+//        }
+//        else if( tag.equals(":write-string")) //event for anything to be output
+//        {
+//          signalListeners(node, SwankEvent.WRITE_STRING);
+//        }
+//        else if( tag.equals(":presentation-start"))
+//        {
+//          signalListeners(node, SwankEvent.PRESENTATION_START);
+//        }
+
+
+
+
         final SwankEvent event = SwankEvent.getEvent(tag);
+
         if( event == SwankEvent.DEFAULT )
         {
           if( tag.equals(":ping") )
       }
     }
 
-    public String fetchText()
-    {
-      synchronized(acc)
-      {
-        String ret = acc.toString();
-        acc = new StringBuffer();
-        return ret;
-      }
-    }
-
     @Override
     public void run()
     {
     public LispNode result = new LispNode();
   }
 
-  public String fetchDisplayText()
-  {
-    return displayListener.fetchText();
-  }
-
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.