Christophe Weblog Wiki Code Publications Music
Add licence information to swank.R
[swankr.git] / swank.R
diff --git a/swank.R b/swank.R
index 05b1c784f6aca534b4361349ba05adb9cc732529..6dca4556d1bb69e787cb4622b8aef2ecd484199c 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -1,3 +1,18 @@
+### This program is free software; you can redistribute it and/or
+### modify it under the terms of the GNU General Public Licence as
+### published by the Free Software Foundation; either version 2 of the
+### Licence, or (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public Licence for more details.
+###
+### A copy of version 2 of the GNU General Public Licence is available
+### at <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>; the
+### latest version of the GNU General Public Licence is available at
+### <http://www.gnu.org/licenses/gpl.txt>.
+
 swank <- function(port=4005) {
   acceptConnections(port, FALSE)
 }
@@ -65,7 +80,7 @@ makeSldbState <- function(condition, level, id) {
 
 sldbLoop <- function(io, sldbState, id) {
   tryCatch({
-    sendToEmacs(io, c(list(quote(`:debug`), id, sldbState$level), debuggerInfoForEmacs(sldbState)))
+    sendToEmacs(io, c(list(quote(`:debug`), id, sldbState$level), `swank:debugger-info-for-emacs`(io, sldbState)))
     sendToEmacs(io, list(quote(`:debug-activate`), id, sldbState$level, FALSE))
     while(TRUE) {
       dispatch(io, readPacket(io), sldbState)
@@ -73,29 +88,6 @@ sldbLoop <- function(io, sldbState, id) {
   }, finally=sendToEmacs(io, c(list(quote(`:debug-return`), id, sldbState$level, FALSE))))
 }
 
-debuggerInfoForEmacs <- function(sldbState, from=0, to=NULL) {
-  backtraceForEmacs <- function() {
-    calls <- sldbState$calls
-    if(is.null(to)) to <- length(calls)
-    from <- from+1
-    calls <- lapply(calls[from:to], { frameNumber <- from-1;
-                             function (x) { ret <- list(frameNumber, paste(format(x), sep="", collapse=" ")); frameNumber <<- 1+frameNumber; ret }})
-  }
-  computeRestartsForEmacs <- function () {
-    lapply(sldbState$restarts,
-           function(x) {
-             ## this is all a little bit internalsy
-             restartName <- x[[1]][[1]]
-             description <- restartDescription(x)
-             list(restartName, if(is.null(description)) restartName else description)
-           })
-  }
-  list(list(as.character(sldbState$condition), sprintf("  [%s]", class(sldbState$condition)[[1]]), FALSE),
-       computeRestartsForEmacs(),
-       backtraceForEmacs(),
-       list(sldbState$id))
-}
-
 readPacket <- function(io) {
   header <- readChunk(io, 6)
   len <- strtoi(header, base=16)
@@ -270,8 +262,35 @@ printToString <- function(val) {
   signalCondition(condition)
 }
 
-`swank:debugger-info-for-emacs` <- function(io, sldbState, from, to) {
-  debuggerInfoForEmacs(sldbState, from=from, to=to)
+`swank:backtrace` <- function(io, sldbState, from=0, to=NULL) {
+  calls <- sldbState$calls
+  if(is.null(to)) to <- length(calls)
+  from <- from+1
+  calls <- lapply(calls[from:to],
+                  { frameNumber <- from-1;
+                    function (x) {
+                      ret <- list(frameNumber, paste(format(x), sep="", collapse=" "))
+                      frameNumber <<- 1+frameNumber
+                      ret
+                    }
+                  })
+}
+
+computeRestartsForEmacs <- function (sldbState) {
+  lapply(sldbState$restarts,
+         function(x) {
+           ## this is all a little bit internalsy
+           restartName <- x[[1]][[1]]
+           description <- restartDescription(x)
+           list(restartName, if(is.null(description)) restartName else description)
+         })
+}
+
+`swank:debugger-info-for-emacs` <- function(io, sldbState, from=0, to=NULL) {
+  list(list(as.character(sldbState$condition), sprintf("  [%s]", class(sldbState$condition)[[1]]), FALSE),
+       computeRestartsForEmacs(sldbState),
+       `swank:backtrace`(io, sldbState, from, to),
+       list(sldbState$id))
 }
 
 `swank:invoke-nth-restart-for-emacs` <- function(io, sldbState, level, n) {
@@ -280,6 +299,21 @@ printToString <- function(val) {
   }
 }
 
+`swank:frame-source-location` <- function(io, sldbState, n) {
+  call <- sldbState$calls[[n+1]]
+  srcref <- attr(call, "srcref")
+  srcfile <- attr(srcref, "srcfile")
+  if(is.null(srcfile)) {
+    list(quote(`:error`), "no srcfile")
+  } else {
+    filename <- get("filename", srcfile)
+    list(quote(`:location`),
+         list(quote(`:file`), filename),
+         list(quote(`:line`), srcref[[1]], srcref[[2]]-1),
+         FALSE)
+  }
+}
+
 `swank:buffer-first-change` <- function(io, sldbState, filename) {
   FALSE
 }
@@ -316,3 +350,29 @@ printToString <- function(val) {
                abort="abort compilation")
   list(quote(`:compilation-result`), list(), TRUE, times[3])
 }
+
+`swank:interactive-eval` <-  function(io, sldbState, string) {
+  retry <- TRUE
+  value <- ""
+  while(retry) {
+    retry <- FALSE
+    withRestarts(value <- eval(parse(text=string), envir = globalenv()),
+                 retry=list(description="retry SLIME interactive evaluation request", handler=function() retry <<- TRUE))
+  }
+  printToString(value)
+}
+
+`swank:eval-and-grab-output` <- function(io, sldbState, string) {
+  retry <- TRUE
+  value <- ""
+  output <- NULL
+  f <- fifo("")
+  tryCatch({
+    sink(f)
+    while(retry) {
+      retry <- FALSE
+      withRestarts(value <- eval(parse(text=string), envir = globalenv()),
+                   retry=list(description="retry SLIME interactive evaluation request", handler=function() retry <<- TRUE))}},
+           finally={sink(); output <- readLines(f); close(f)})
+  list(output, printToString(value))
+}