/[slime]/slime/swank-backend.lisp
ViewVC logotype

Contents of /slime/swank-backend.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (hide annotations)
Tue Dec 16 10:28:42 2003 UTC (10 years, 4 months ago) by lgorrie
Branch: MAIN
Changes since 1.9: +3 -1 lines
Exported invoke-nth-restart-for-emacs and sldb-break-with-default-debugger.
1 lgorrie 1.1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil; outline-regexp: ";;;;;*" -*-
2     ;;;
3     ;;; slime-impl.lisp --- Slime interface reference implementation.
4     ;;;
5     ;;; Copyright (C) 2003, James Bielman <jamesjb@jamesjb.com>
6     ;;; Released into the public domain.
7     ;;;
8 lgorrie 1.10 ;;; $Id: swank-backend.lisp,v 1.10 2003/12/16 10:28:42 lgorrie Exp $
9 lgorrie 1.1 ;;;
10    
11     ;; This is a skeletal implementation of the Slime internals interface.
12     ;;
13     ;; The idea is to create a de-facto standard interface that can be
14     ;; used by editor <-> CL integration software, such as Slime. Vendors
15     ;; are encouraged to comment on this interface.
16    
17     (defpackage :swank
18     (:use :common-lisp)
19 lgorrie 1.3 (:nicknames #:swank-backend)
20 lgorrie 1.9 (:export #:*sldb-pprint-frames*
21     #:apropos-list-for-emacs
22     #:arglist-string
23     #:backtrace
24     #:call-with-I/O-lock
25     #:call-with-conversation-lock
26 heller 1.5 #:compiler-notes-for-emacs
27 lgorrie 1.9 #:completions
28     #:create-swank-server
29     #:describe-alien-enum
30     #:describe-alien-struct
31 heller 1.5 #:describe-alien-type
32 lgorrie 1.9 #:describe-alien-union
33     #:describe-class
34 heller 1.5 #:describe-function
35     #:describe-inspectee
36     #:describe-setf-function
37 lgorrie 1.9 #:describe-symbol
38     #:describe-type
39     #:disassemble-symbol
40 heller 1.5 #:documentation-symbol
41 lgorrie 1.9 #:eval-in-frame
42     #:eval-string
43     #:eval-string-in-frame
44 heller 1.7 #:find-function-locations
45 heller 1.5 #:frame-catch-tags
46 lgorrie 1.9 #:frame-locals
47     #:frame-source-location-for-emacs
48 heller 1.5 #:frame-source-position
49 lgorrie 1.9 #:getpid
50     #:give-goahead
51     #:give-gohead
52     #:init-inspector
53     #:inspect-in-frame
54     #:inspect-nth-part
55     #:inspector-next
56 heller 1.5 #:inspector-pop
57 lgorrie 1.9 #:interactive-eval
58     #:interactive-eval-region
59 heller 1.5 #:invoke-nth-restart
60 lgorrie 1.10 #:invoke-nth-restart-for-emacs
61 lgorrie 1.9 #:list-all-package-names
62     #:list-callees
63     #:list-callers
64     #:listener-eval
65     #:load-file
66     #:pprint-eval
67 heller 1.5 #:pprint-eval-string-in-frame
68 lgorrie 1.9 #:quit-inspector
69     #:re-evaluate-defvar
70     #:set-default-directory
71     #:set-package
72 heller 1.5 #:sldb-abort
73 lgorrie 1.10 #:sldb-break-with-default-debugger
74 heller 1.5 #:sldb-continue
75 lgorrie 1.9 #:slime-debugger-function
76     #:start-server
77     #:startup-multiprocessing
78     #:startup-multiprocessing-for-emacs
79     #:swank-compile-file
80     #:swank-compile-string
81     #:swank-macroexpand
82     #:swank-macroexpand-1
83     #:swank-macroexpand-all
84 heller 1.5 #:take-input
85 lgorrie 1.9 #:thread-id
86     #:thread-name
87     #:throw-to-toplevel
88     #:toggle-trace-fdefinition
89     #:untrace-all
90     #:wait-goahead
91     #:who-binds
92     #:who-calls
93     #:who-macroexpands
94     #:who-references
95     #:who-sets
96 heller 1.5 ))
97 lgorrie 1.1
98     (in-package :swank)
99    
100    
101     ;;;; Conditions and Error Handling
102    
103     ;; XXX need to specify restart behavior for errors/warnings?
104    
105     (define-condition not-implemented-error (error)
106     ())
107    
108     (deftype severity () '(member :error :warning :style-warning :note))
109    
110     ;; Base condition type for compiler errors, warnings and notes.
111     (define-condition compiler-condition (condition)
112     ((original-condition
113     ;; The original condition thrown by the compiler if appropriate.
114     ;; May be NIL if a compiler does not report using conditions.
115     :initarg :original-condition
116     :accessor original-condition)
117    
118     (severity
119     :type severity
120     :initarg :severity
121     :accessor severity)
122    
123     (message
124     :initarg :message
125     :accessor message)
126    
127     (location
128     :initarg :location
129     :accessor location)))
130    
131    
132     ;;;; Compilation
133 dbarlow 1.8
134     (defgeneric call-with-compilation-hooks (func)
135     (:documentation
136     "Call FUNC with hooks to trigger SLDB on compiler errors."))
137     (defmacro with-compilation-hooks (() &body body)
138     `(call-with-compilation-hooks (lambda () (progn ,@body))))
139 lgorrie 1.1
140     (defgeneric compile-string-for-emacs (string &key buffer position)
141     (:documentation
142     "Compile source from STRING. During compilation, compiler
143     conditions must be trapped and resignalled as COMPILER-CONDITIONs.
144    
145     If supplied, BUFFER and POSITION specify the source location in Emacs.
146    
147     Additionally, if POSITION is supplied, it must be added to source
148     positions reported in compiler conditions."))
149    
150     (defgeneric compile-file-for-emacs (filename load-p)
151     (:documentation
152     "Compile FILENAME signalling COMPILE-CONDITIONs.
153     If LOAD-P is true, load the file after compilation."))
154    
155    
156     ;;;; Documentation
157    
158     (defgeneric arglist-string (function-name)
159     (:documentation
160     "Return the argument for FUNCTION-NAME as a string.
161     The result should begin and end with parenthesis."))
162    
163     (defgeneric macroexpand-all (form)
164     (:documentation
165     "Recursively expand all macros in FORM.
166     Return the resulting form."))
167    
168     (defgeneric describe-symbol-for-emacs (symbol)
169     (:documentation
170     "Return a property list describing SYMBOL.
171    
172     The property list has an entry for each interesting aspect of the
173     symbol. The recognised keys are:
174    
175     :VARIABLE :FUNCTION :SETF :TYPE :CLASS :MACRO :COMPILER-MACRO
176     :ALIEN-TYPE :ALIEN-STRUCT :ALIEN-UNION :ALIEN-ENUM
177    
178     The value of each property is the corresponding documentation string,
179     or :NOT-DOCUMENTED. It is legal to include keys not listed here.
180    
181     Properties should be included if and only if they are applicable to
182     the symbol. For example, only (and all) fbound symbols should include
183     the :FUNCTION property.
184    
185     Example:
186     \(describe-symbol-for-emacs 'vector)
187     => (:CLASS :NOT-DOCUMENTED
188     :TYPE :NOT-DOCUMENTED
189     :FUNCTION \"Constructs a simple-vector from the given objects.\")"))
190 lgorrie 1.2
191    
192     ;;;; Debugging
193    
194     (defgeneric call-with-debugging-environment (debugger-loop-fn)
195     (:documentation
196     "Call DEBUGGER-LOOP-FN in a suitable debugging environment.
197    
198     This function is called recursively at each debug level to invoke the
199     debugger loop. The purpose is to setup any necessary environment for
200     other debugger callbacks that will be called within the debugger loop.
201    
202     For example, this is a reasonable place to compute a backtrace, switch
203     to safe reader/printer settings, and so on."))
204    
205     (define-condition sldb-condition (condition)
206     ((original-condition
207     :initarg :original-condition
208 heller 1.5 :accessor original-condition))
209 lgorrie 1.2 (:documentation
210     "Wrapper for conditions that should not be debugged.
211    
212     When a condition arises from the internals of the debugger, it is not
213     desirable to debug it -- we'd risk entering an endless loop trying to
214     debug the debugger! Instead, such conditions can be reported to the
215     user without (re)entering the debugger by wrapping them as
216     `sldb-condition's."))
217    
218     (defgeneric debugger-info-for-emacs (start end)
219     (:documentation
220     "Return debugger state, with stack frames from START to END.
221     The result is a list:
222     (condition-description ({restart}*) ({stack-frame}*)
223     where
224     restart ::= (name description)
225     stack-frame ::= (number description)
226    
227     condition-description---a string describing the condition that
228     triggered the debugger.
229    
230     restart---a pair of strings: restart name, and description.
231    
232     stack-frame---a number from zero (the top), and a printed
233     representation of the frame's call.
234    
235     Below is an example return value. In this case the condition was a
236     division by zero (multi-line description), and only one frame is being
237     fetched (start=0, end=1).
238    
239     (\"Arithmetic error DIVISION-BY-ZERO signalled.
240     Operation was KERNEL::DIVISION, operands (1 0).
241     [Condition of type DIVISION-BY-ZERO]\"
242     ((\"ABORT\" \"Return to Slime toplevel.\")
243     (\"ABORT\" \"Return to Top-Level.\"))
244     ((0 \"0: (KERNEL::INTEGER-/-INTEGER 1 0)\")))"))
245 lgorrie 1.1
246 lgorrie 1.3 (defgeneric backtrace (start end)
247     (:documentation
248     "Return a list containing a backtrace of the condition current
249     being debugged. The results are unspecified if this function is
250     called outside the dynamic contour of a debugger hook defined by
251     DEFINE-DEBUGGER-HOOK.
252    
253     START and END are zero-based indices constraining the number of
254     frames returned. Frame zero is defined as the frame which invoked
255     the debugger.
256    
257     The backtrace is returned as a list of tuples of the form
258     \(FRAME-NUMBER FRAME-DESCRIPTION), where FRAME-NUMBER is the
259     index of the frame, defined like START/END, and FRAME-DESCRIPTION
260     is a string containing text to display in the debugger for this
261     frame.
262    
263     An example return value:
264    
265     ((0 \"(HELLO \"world\")\")
266     (1 \"(RUN-EXCITING-LISP-DEMO)\")
267     (2 \"(SYS::%TOPLEVEL #<SYS::ENVIRONMENT #x394834>)\"))"))
268    
269     (defgeneric frame-source-location-for-emacs (frame-number)
270     (:documentation
271     "Return the source location for FRAME-NUMBER."))
272    
273     (defgeneric frame-catch-tags (frame-number)
274     (:documentation
275     "Return a list of XXX list of what? catch tags for a debugger
276     stack frame. The results are undefined unless this is called
277     within the dynamic contour of a function defined by
278     DEFINE-DEBUGGER-HOOK."))
279    
280     (defgeneric frame-locals (frame-number)
281     (:documentation
282     "Return a list of XXX local variable designators define me
283     for a debugger stack frame. The results are undefined unless
284     this is called within the dynamic contour of a function defined
285     by DEFINE-DEBUGGER-HOOK."))
286    
287     (defgeneric eval-in-frame (form frame-number)
288     (:documentation
289     "Evaluate a Lisp form in the lexical context of a stack frame
290     in the debugger. The results are undefined unless called in the
291     dynamic contour of a function defined by DEFINE-DEBUGGER-HOOK.
292    
293     FRAME-NUMBER must be a positive integer with 0 indicating the
294     frame which invoked the debugger.
295    
296     The return value is the result of evaulating FORM in the
297     appropriate context."))
298    
299    
300     ;;;; Queries
301    
302 heller 1.7 #+(or)
303     ;;; This is probably a better interface than find-function-locations.
304     (defgeneric find-definitions (name)
305 lgorrie 1.3 (:documentation
306 heller 1.7 "Return a list of (LABEL . LOCATION) pairs for NAME's definitions.
307 lgorrie 1.3
308 heller 1.7 NAME is string denoting a symbol or \"definition specifier\".
309    
310     LABEL is a string describing the definition, e.g., \"foo\" or
311     \"(method foo (string number))\" or \"(variable bar)\".
312    
313     LOCATION is a source location of the form:
314    
315     <location> ::= (:location <buffer> <position>)
316     | (:error <message>)
317    
318     <buffer> ::= (:file <filename>)
319     | (:buffer <buffername>)
320     | (:source-form <string>)
321    
322     <position> ::= (:position <fixnum> [<align>]) ; 1 based
323     | (:function-name <string>)
324     "))
325    
326     (defgeneric find-function-locations (name)
327     (:documentation
328     "Return a list (LOCATION LOCATION ...) for NAME's definitions.
329    
330     LOCATION is a source location of the form:
331    
332     <location> ::= (:location <buffer> <position>)
333     | (:error <message>)
334    
335     <buffer> ::= (:file <filename>)
336     | (:buffer <buffername>)
337     | (:source-form <string>)
338    
339     <position> ::= (:position <fixnum> [<align>]) ; 1 based
340     | (:function-name <string>)"))
341 lgorrie 1.9
342    
343     ;;;; Multiprocessing
344    
345     (defgeneric startup-multiprocessing ()
346     (:documentation
347     "Initialize multiprocessing, if necessary.
348    
349     This function is called directly through the listener, not in an RPC
350     from Emacs. This is to support interfaces such as CMUCL's
351     MP::STARTUP-IDLE-AND-TOP-LEVEL-LOOPS which does not return like a
352     normal function."))
353    
354     (defgeneric thread-id ()
355     (:documentation
356     "Return a value that uniquely identifies the current thread.
357     Thread-IDs allow Emacs to refer to individual threads.
358    
359     When called several times by the same thread, all return values are
360     EQUAL. The value has a READable printed representation that preserves
361     equality. The printed representation must be identical in Emacs Lisp
362     and Common Lisp, and short enough to include in the REPL prompt.
363    
364     For example, a THREAD-ID could be an integer or a short ASCII string.
365    
366     Systems that do not support multiprocessing return NIL."))
367    
368     (defgeneric thread-name (thread-id)
369     (:documentation
370     "Return the name of the thread identified by THREAD-ID.
371    
372     Thread names are be single-line strings and are meaningful to the
373     user. They do not have to be unique."))
374    
375     (defgeneric call-with-I/O-lock (function)
376     (:documentation
377     "Call FUNCTION with the \"I/O\" lock held.
378     Only one thread can hold the I/O lock at a time -- others are blocked
379     until they acquire it. When called recursively (i.e. lock already
380     held), simply calls FUNCTION.
381    
382     This is a low-level lock used for mutual exclusion on individual
383     messages read and written to the socket connecting Emacs.
384    
385     Systems that do not support multiprocessing simply call FUNCTION."))
386    
387     (defgeneric call-with-conversation-lock (function)
388     (:documentation
389     "Call FUNCTION with the \"conversation\" lock held.
390     The semantics are analogous to CALL-WITH-I/O-HOOK.
391    
392     This is a high-level lock used for mutual exclusion in conversations
393     with Emacs that can span multiple messages. The I/O lock must
394     separately be held when reading and writing individual messages."))
395    
396     ;;; Functions for attracting the Emacs user's attention.
397    
398     (defgeneric wait-goahead ()
399     (:documentation
400     "Block until told to continue by `give-gohead'.
401    
402     Systems that do not support multiprocessing return immediately."))
403    
404     (defgeneric give-goahead (thread-id)
405     (:documentation
406     "Permit THREAD-ID to continue from WAIT-GOAHEAD.
407     It is an error to call (GIVE-GOAHEAD ID) unless ID is blocking in
408     WAIT-GOAHEAD.
409    
410     Systems that do not support multiprocessing always signal an error."))
411    
412     ;;;;; Default implementation for non-MP systems
413    
414     ;;; Using NO-APPLICABLE-METHOD to supply a default implementation that
415     ;;; works in systems that don't have multiprocessing.
416     ;;; (Good or bad idea? -luke)
417    
418     (defvar _ nil ; Good or bad idea? -luke
419     "Null variable -- can be used for ignored arguments.
420     Declared special, so no IGNORE declarations are necessary.")
421    
422     (defmethod no-applicable-method ((m (eql #'startup-multiprocessing)) &rest _)
423     nil)
424     (defmethod no-applicable-method ((m (eql #'thread-id)) &rest _)
425     nil)
426     (defmethod no-applicable-method ((m (eql #'thread-name)) &rest _)
427     "The One True Thread")
428     (defmethod no-applicable-method ((m (eql #'call-with-I/O-lock))
429     &rest args)
430     (funcall (first args)))
431     (defmethod no-applicable-method ((m (eql #'call-with-conversation-lock))
432     &rest args)
433     (funcall (first args)))
434     (defmethod no-applicable-method ((m (eql #'wait-goahead)) &rest _)
435     t)
436     (defmethod no-applicable-method ((m (eql #'give-goahead)) &rest _)
437     (error "SLIME multiprocessing not available"))
438 lgorrie 1.1

  ViewVC Help
Powered by ViewVC 1.1.5