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

Contents of /slime/swank-backend.lisp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5