Hi guys,
how easily can slime be modified to support non-common-lisp languages? I have one in mind that I'd love to use with slime...
thanks!
tom scrawler@gmail.com writes:
Hi guys,
how easily can slime be modified to support non-common-lisp languages? I have one in mind that I'd love to use with slime...
Good question.
Basically SLIME does not care what it is talking to. The over-the-wire protocol is S-expressions but they are just messages, not Lisp code. There are some Common Lisp'ey notions though, like current package.
One way to get a basic idea is to use SLIME for a while and then look in the *slime-events* buffer to see what messages have been exchanged. Here's an edited transcript with some comments:
;; Lisp->Emacs: Connect to port 33522 to read Lisp *standard-output* (:open-dedicated-output-stream 33522)
;; Lisp->Emacs: Setup indentation for these macros I've discovered (:indentation-update (("output-wrapper" . 1) ("def-output-routines" . 1) ("with-pathname" . 1) ("with-host" . 1) ("with-read-buffer" . 1) ("prepare-for-fast-read-char" . 1) ("maybe-sap-maybe-string" . 1) ("input-wrapper" . 1) ("enumerate-matches" . 1) ("with-symbol" . 1) ("prepare-for-fast-read-byte" . 1) ("with-fop-stack" . 1) ("without-package-locks" . 0) ("enumerate-search-list" . 1) ("def-source-context" . 2) ("do-info" . 1) ("with-float-traps-masked" . 1) ("define-function-name-syntax" . 2) ("with-c-strvec" . 1) ("descend-into" . 1) ...))
;; Emacs->Lisp (RPC request): Tell me about yourself. (:emacs-rex (swank:connection-info) nil t 1)
;; Lisp->Emacs (RPC result): My PID is 7852, I'm running CMU Common ;; Lisp, and this is my *FEATURES* list. (:return (:ok (7852 "CMU Common Lisp" "cmucl" (:cmu-hooks-require :asdf-install :split-sequence :asdf :gerds-pcl :pcl-structures :portable-commonloops :pcl :cmu19 :cmu19a :python :conservative-float-type :modular-arith :cmucl-19a-patch-002 :cmucl-19a-patch-001 :cmucl-19a-patch-000 :mp :x86 :linkage-table :relative-package-names ...) :sigio)) 1)
Now I type in the REPL..
;; Emacs->Lisp: Please eval the string "123\n" using the REPL's ;; thread and the COMMON-LISP-USER package and send me the result. (:emacs-rex (swank:listener-eval "123\n") "COMMON-LISP-USER" :repl-thread 2) ;; Lisp->Emacs: The result prints as "123" (:return (:ok "123") 2)
Now I open a file and use `C-c C-c' to compile a defun..
;; Emacs->Lisp: Please compile this string. (:emacs-rex (swank:compile-string-for-emacs "(defun add1 (x)\n (+ x 1))\n" "x.lisp" 1 "/tmp/") nil t 14) ;; Lisp->Emacs: Done. There were no errors and compilation took 0.06 secs. (:return (:ok ("NIL" "0.06")) 14)
Now I do M-. on the `add1' function that I just defined:
;; Emacs->Lisp: Where are the definition(s) of `add1'? (:emacs-rex (swank:find-definitions-for-emacs "add1") nil t 18)
;; Lisp-Emacs: There is one definition, it's at position 1 of your ;; buffer called x.lisp. In case it moved here's a snippet of its ;; source -- you could search for a definition that starts in the ;; same way. (:return (:ok (("#'ADD1" (:location (:buffer "x.lisp") (:position 1) (:snippet "(defun add1 (x)\n (+ x 1))\n"))))) 18)
.. and so on.
Most dialogue between Emacs and Lisp are RPCs that get translated into APPLY's of functions in swank.lisp that are defined with DEFSLIMEFUN.
You can see most of the interface with: grep defslimefun swank.lisp
but there are also functions in swank-backend.lisp that are callable from Emacs. You can see which ones in the export list at the top of swank.lisp.
Cheerio, Luke
tom scrawler@gmail.com writes:
Hi guys,
how easily can slime be modified to support non-common-lisp languages? I have one in mind that I'd love to use with slime...
Below is some code to use SLIME with Scheme48. You can start it with M-x slime48.
Only a few things work: evaluation, inspecting, apropos (a bit), backtraces.
Interrupting doesn't work. This could be implemented with threads, but would have been painful in 0.57. They changed the threading interface in the latest version (i think 0.57.1). It might be easier there.
Currently, everything is evaluated in the SWANK package/module. It might be a good idea to have something like a current interaction environment.
M-. (find-definition) is also missing. AFAICT, Scheme48 doesn't keep enough information around for a reliable M-. command. It's probably possible to find the package (module) for a definition and the default file for that package. ISTR, that Scheme48 can be configured differently, so that all interface/structure/package information is accessible in a central place. That might be a good idea. (In the default configuration, the information about modules is distributed, more or less randomly, in many different environments.)
The Swank code will very likely break if you grab a continuation and return to the Swank code a second time.
I haven't use the scheme48 stuff in anger but there are obvious limitations. If you want to use Scheme seriously, it might be easier to start from scratch, i.e., reimplement the Emacs Lisp side.
Helmut.
(defun slime48 () (interactive) (require 'slime) (let ((proc (slime-start-lisp "s48" (get-buffer-create "*s48*") (concat ",config\n" ",load " slime-path"swank-scheme48.scm\n" ",in swank\n" (format "(start-swank %S)" (slime-swank-port-file)) "\n")))) (slime-read-port-and-connect proc nil)))