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

Contents of /slime/swank-backend.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.38 - (hide annotations)
Fri Mar 12 21:16:08 2004 UTC (10 years, 1 month ago) by heller
Branch: MAIN
Changes since 1.37: +5 -3 lines
(find-definitions): Fix docstring.
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 heller 1.36 (defpackage :swank-backend
12 lgorrie 1.1 (:use :common-lisp)
13 heller 1.36 (:export #:sldb-condition
14     #:original-condition
15     #:compiler-condition
16     #:message
17     #:short-message
18     #:condition
19     #:severity
20     #:location
21     #:location-p
22     #:location-buffer
23     #:location-position
24     #:position-p
25     #:position-pos
26     #:print-output-to-string
27 heller 1.5 ))
28 lgorrie 1.1
29 heller 1.36 (in-package :swank-backend)
30 lgorrie 1.1
31    
32 lgorrie 1.21 ;;;; Metacode
33    
34     (defparameter *interface-functions* '()
35     "The names of all interface functions.")
36    
37     (defparameter *unimplemented-interfaces* '()
38     "List of interface functions that are not implemented.
39     DEFINTERFACE adds to this list and DEFIMPLEMENTATION removes.")
40    
41     (defmacro definterface (name args documentation &body default-body)
42     "Define an interface function for the backend to implement.
43     A generic function is defined with NAME, ARGS, and DOCUMENTATION.
44    
45     If a DEFAULT-BODY is supplied then NO-APPLICABLE-METHOD is specialized
46     to execute the body if the backend doesn't provide a specific
47     implementation.
48    
49     Backends implement these functions using DEFIMPLEMENTATION."
50     (flet ((gen-default-impl ()
51     (let ((received-args (gensym "ARGS-")))
52     `(defmethod no-applicable-method ((#:method
53     (eql (function ,name)))
54     &rest ,received-args)
55     (destructuring-bind ,args ,received-args
56     ,@default-body)))))
57 heller 1.36 ` (progn (defgeneric ,name ,args (:documentation ,documentation))
58     (pushnew ',name *interface-functions*)
59     ,(if (null default-body)
60     `(pushnew ',name *unimplemented-interfaces*)
61     (gen-default-impl))
62     (export ',name :swank-backend)
63     ',name)))
64 lgorrie 1.21
65     (defmacro defimplementation (name args &body body)
66     ;; Is this a macro no-no -- should it be pushed out of macroexpansion?
67 heller 1.25 `(progn (defmethod ,name ,args ,@body)
68     (if (member ',name *interface-functions*)
69     (setq *unimplemented-interfaces*
70     (remove ',name *unimplemented-interfaces*))
71     (warn "DEFIMPLEMENTATION of undefined interface (~S)" ',name))
72     ',name))
73 lgorrie 1.21
74     (defun warn-unimplemented-interfaces ()
75     "Warn the user about unimplemented backend features.
76     The portable code calls this function at startup."
77     (warn "These Swank interfaces are unimplemented:~% ~A"
78     (sort (copy-list *unimplemented-interfaces*) #'string<)))
79    
80    
81 lgorrie 1.13 ;;;; TCP server
82    
83 heller 1.29 (definterface create-socket (host port)
84     "Create a listening TCP socket on interface HOST and port PORT .")
85 lgorrie 1.13
86 lgorrie 1.21 (definterface local-port (socket)
87     "Return the local port number of SOCKET.")
88 lgorrie 1.1
89 lgorrie 1.21 (definterface close-socket (socket)
90     "Close the socket SOCKET.")
91 lgorrie 1.1
92 lgorrie 1.21 (definterface accept-connection (socket)
93 heller 1.16 "Accept a client connection on the listening socket SOCKET. Return
94 lgorrie 1.21 a stream for the new connection.")
95 heller 1.16
96 heller 1.31 (definterface add-sigio-handler (socket fn)
97 lgorrie 1.21 "Call FN whenever SOCKET is readable.")
98 heller 1.16
99 heller 1.31 (definterface remove-sigio-handlers (socket)
100     "Remove all sigio handlers for SOCKET.")
101    
102     (definterface add-fd-handler (socket fn)
103     "Call FN when Lisp is waiting for input and SOCKET is readable.")
104    
105     (definterface remove-fd-handlers (socket)
106     "Remove all fd-handlers for SOCKET.")
107 heller 1.18
108 heller 1.36 (definterface preferred-communication-style ()
109     "Return one of the symbols :spawn, :sigio, :fd-handler, or NIL."
110     nil)
111    
112 lgorrie 1.13 ;;; Base condition for networking errors.
113     (define-condition network-error (error) ())
114    
115 lgorrie 1.21 (definterface emacs-connected ()
116 lgorrie 1.13 "Hook called when the first connection from Emacs is established.
117     Called from the INIT-FN of the socket server that accepts the
118     connection.
119 lgorrie 1.1
120 lgorrie 1.13 This is intended for setting up extra context, e.g. to discover
121 lgorrie 1.21 that the calling thread is the one that interacts with Emacs."
122     nil)
123 lgorrie 1.1
124    
125 heller 1.20 ;;;; Unix signals
126    
127     (defconstant +sigint+ 2)
128    
129 heller 1.36 (definterface call-without-interrupts (fn)
130     "Call FN in a context where interrupts are disabled."
131     (funcall fn))
132 heller 1.20
133 heller 1.32 (definterface getpid ()
134     "Return the (Unix) process ID of this superior Lisp.")
135    
136     (definterface lisp-implementation-type-name ()
137     "Return a short name for the Lisp implementation."
138     (lisp-implementation-type))
139 heller 1.20
140    
141 lgorrie 1.1 ;;;; Compilation
142 dbarlow 1.8
143 lgorrie 1.21 (definterface call-with-compilation-hooks (func)
144     "Call FUNC with hooks to trigger SLDB on compiler errors.")
145 lgorrie 1.13
146 vsedach 1.14 (defmacro with-compilation-hooks ((&rest ignore) &body body)
147     (declare (ignore ignore))
148 dbarlow 1.8 `(call-with-compilation-hooks (lambda () (progn ,@body))))
149 lgorrie 1.1
150 heller 1.36 (definterface swank-compile-string (string &key buffer position)
151 lgorrie 1.1 "Compile source from STRING. During compilation, compiler
152     conditions must be trapped and resignalled as COMPILER-CONDITIONs.
153    
154     If supplied, BUFFER and POSITION specify the source location in Emacs.
155    
156     Additionally, if POSITION is supplied, it must be added to source
157 lgorrie 1.21 positions reported in compiler conditions.")
158 lgorrie 1.1
159 heller 1.36 (definterface swank-compile-system (system-name)
160 mbaringer 1.26 "Compile and load SYSTEM-NAME, During compilation compiler
161     conditions must be trapped and resignalled as
162 heller 1.30 COMPILER-CONDITION ala compile-string-for-emacs."
163     (with-compilation-hooks ()
164     (cond ((member :asdf *features*)
165     (let ((operate (find-symbol (string :operate) :asdf))
166     (load-op (find-symbol (string :load-op) :asdf)))
167     (funcall operate load-op system-name)))
168     (t (error "ASDF not loaded")))))
169 mbaringer 1.26
170 heller 1.36 (definterface swank-compile-file (filename load-p)
171 lgorrie 1.1 "Compile FILENAME signalling COMPILE-CONDITIONs.
172 lgorrie 1.21 If LOAD-P is true, load the file after compilation.")
173 lgorrie 1.1
174 lgorrie 1.13 (deftype severity () '(member :error :warning :style-warning :note))
175    
176     ;; Base condition type for compiler errors, warnings and notes.
177     (define-condition compiler-condition (condition)
178     ((original-condition
179     ;; The original condition thrown by the compiler if appropriate.
180     ;; May be NIL if a compiler does not report using conditions.
181     :type (or null condition)
182     :initarg :original-condition
183     :accessor original-condition)
184    
185     (severity :type severity
186     :initarg :severity
187     :accessor severity)
188    
189     (message :initarg :message
190     :accessor message)
191    
192 heller 1.30 (short-message :initarg :short-message
193     :initform nil
194     :accessor short-message)
195    
196 lgorrie 1.13 (location :initarg :location
197     :accessor location)))
198 heller 1.30
199    
200 lgorrie 1.13
201 lgorrie 1.17
202 lgorrie 1.13 ;;;; Streams
203    
204 lgorrie 1.21 (definterface make-fn-streams (input-fn output-fn)
205 lgorrie 1.13 "Return character input and output streams backended by functions.
206     When input is needed, INPUT-FN is called with no arguments to
207     return a string.
208     When output is ready, OUTPUT-FN is called with the output as its
209     argument.
210    
211     Output should be forced to OUTPUT-FN before calling INPUT-FN.
212    
213 lgorrie 1.21 The streams are returned as two values.")
214 lgorrie 1.13
215 lgorrie 1.1
216     ;;;; Documentation
217    
218 heller 1.36 (definterface arglist (name)
219     "Return the lambda list for the symbol NAME.
220    
221     The result can be a list or a string.
222    
223     An error should be signaled if the lambda list cannot be found.")
224 lgorrie 1.1
225 lgorrie 1.21 (definterface macroexpand-all (form)
226 lgorrie 1.1 "Recursively expand all macros in FORM.
227 lgorrie 1.21 Return the resulting form.")
228 lgorrie 1.1
229 lgorrie 1.21 (definterface describe-symbol-for-emacs (symbol)
230 lgorrie 1.1 "Return a property list describing SYMBOL.
231    
232     The property list has an entry for each interesting aspect of the
233     symbol. The recognised keys are:
234    
235     :VARIABLE :FUNCTION :SETF :TYPE :CLASS :MACRO :COMPILER-MACRO
236     :ALIEN-TYPE :ALIEN-STRUCT :ALIEN-UNION :ALIEN-ENUM
237    
238     The value of each property is the corresponding documentation string,
239     or :NOT-DOCUMENTED. It is legal to include keys not listed here.
240    
241     Properties should be included if and only if they are applicable to
242     the symbol. For example, only (and all) fbound symbols should include
243     the :FUNCTION property.
244    
245     Example:
246     \(describe-symbol-for-emacs 'vector)
247     => (:CLASS :NOT-DOCUMENTED
248     :TYPE :NOT-DOCUMENTED
249 lgorrie 1.21 :FUNCTION \"Constructs a simple-vector from the given objects.\")")
250    
251     (definterface describe-definition (name type)
252     "Describe the definition NAME of TYPE.
253     TYPE can be any value returned by DESCRIBE-SYMBOL-FOR-EMACS.
254    
255     Return a documentation string, or NIL if none is available.")
256 lgorrie 1.2
257    
258     ;;;; Debugging
259    
260 lgorrie 1.21 (definterface call-with-debugging-environment (debugger-loop-fn)
261 lgorrie 1.2 "Call DEBUGGER-LOOP-FN in a suitable debugging environment.
262    
263     This function is called recursively at each debug level to invoke the
264     debugger loop. The purpose is to setup any necessary environment for
265     other debugger callbacks that will be called within the debugger loop.
266    
267     For example, this is a reasonable place to compute a backtrace, switch
268 lgorrie 1.21 to safe reader/printer settings, and so on.")
269 lgorrie 1.2
270     (define-condition sldb-condition (condition)
271     ((original-condition
272     :initarg :original-condition
273 heller 1.5 :accessor original-condition))
274 lgorrie 1.2 (:documentation
275     "Wrapper for conditions that should not be debugged.
276    
277     When a condition arises from the internals of the debugger, it is not
278     desirable to debug it -- we'd risk entering an endless loop trying to
279     debug the debugger! Instead, such conditions can be reported to the
280     user without (re)entering the debugger by wrapping them as
281     `sldb-condition's."))
282    
283 heller 1.36 (definterface compute-backtrace (start end)
284 lgorrie 1.3 "Return a list containing a backtrace of the condition current
285     being debugged. The results are unspecified if this function is
286 heller 1.36 called outside the dynamic contour CALL-WITH-DEBUGGING-ENVIRONMENT.
287    
288     START and END are zero-based indices constraining the number of frames
289     returned. Frame zero is defined as the frame which invoked the
290     debugger. If END is nil, return the frames from START to the end of
291     the stack.")
292 lgorrie 1.3
293 heller 1.36 (definterface print-frame (frame stream)
294     "Print frame to stream.")
295 lgorrie 1.3
296 lgorrie 1.21 (definterface frame-source-location-for-emacs (frame-number)
297     "Return the source location for FRAME-NUMBER.")
298 lgorrie 1.3
299 lgorrie 1.21 (definterface frame-catch-tags (frame-number)
300 lgorrie 1.3 "Return a list of XXX list of what? catch tags for a debugger
301     stack frame. The results are undefined unless this is called
302     within the dynamic contour of a function defined by
303 lgorrie 1.21 DEFINE-DEBUGGER-HOOK.")
304 lgorrie 1.3
305 lgorrie 1.21 (definterface frame-locals (frame-number)
306 lgorrie 1.3 "Return a list of XXX local variable designators define me
307     for a debugger stack frame. The results are undefined unless
308     this is called within the dynamic contour of a function defined
309 lgorrie 1.21 by DEFINE-DEBUGGER-HOOK.")
310 heller 1.37
311     (definterface disassemble-frame (frame-number)
312     "Disassemble the code for the FRAME-NUMBER.
313     The output should be written to standard output.
314     FRAME-NUMBER is a non-negative interger.")
315    
316 lgorrie 1.21 (definterface eval-in-frame (form frame-number)
317 lgorrie 1.3 "Evaluate a Lisp form in the lexical context of a stack frame
318     in the debugger. The results are undefined unless called in the
319     dynamic contour of a function defined by DEFINE-DEBUGGER-HOOK.
320    
321     FRAME-NUMBER must be a positive integer with 0 indicating the
322     frame which invoked the debugger.
323    
324     The return value is the result of evaulating FORM in the
325 lgorrie 1.21 appropriate context.")
326 heller 1.22
327     (definterface return-from-frame (frame-number form)
328     "Unwind the stack to the frame FRAME-NUMBER and return the value(s)
329     produced by evaluating FORM in the frame context to its caller.
330    
331     Execute any clean-up code from unwind-protect forms above the frame
332     during unwinding.
333    
334     Return a string describing the error if it's not possible to return
335     from the frame.")
336    
337     (definterface restart-frame (frame-number)
338     "Restart execution of the frame FRAME-NUMBER with the same arguments
339     as it was called originally.")
340 lgorrie 1.3
341    
342 heller 1.36 ;;;; Definition finding
343    
344     (defstruct (:location (:type list) :named
345     (:constructor make-location (buffer position)))
346     buffer position)
347    
348     (defstruct (:error (:type list) :named (:constructor)) message)
349     (defstruct (:file (:type list) :named (:constructor)) name)
350     (defstruct (:buffer (:type list) :named (:constructor)) name)
351     (defstruct (:position (:type list) :named (:constructor)) pos)
352    
353     (definterface find-definitions (name)
354     "Return a list ((DSPEC LOCATION) ...) for NAME's definitions.
355    
356 heller 1.38 NAME is a \"definition specifier\".
357 heller 1.36
358 heller 1.38 DSPEC is a \"definition specifier\" describing the
359 heller 1.36 definition, e.g., FOO or (METHOD FOO (STRING NUMBER)) or
360 heller 1.38 \(DEFVAR FOO).
361    
362     LOCATION is the source location for the definition.")
363 heller 1.36
364    
365     ;;;; XREF
366    
367     (definterface who-calls (function-name)
368     "Return the call sites of FUNCTION-NAME (a symbol).
369     The results is a list ((DSPEC LOCATION) ...).")
370    
371     (definterface who-references (variable-name)
372     "Return the locations where VARIABLE-NAME (a symbol) is referenced.
373     See WHO-CALLS for a description of the return value.")
374    
375     (definterface who-binds (variable-name)
376     "Return the locations where VARIABLE-NAME (a symbol) is bound.
377     See WHO-CALLS for a description of the return value.")
378    
379     (definterface who-sets (variable-name)
380     "Return the locations where VARIABLE-NAME (a symbol) is set.
381     See WHO-CALLS for a description of the return value.")
382    
383     (definterface who-macroexpands (macro-name)
384     "Return the locations where MACRO-NAME (a symbol) is expanded.
385     See WHO-CALLS for a description of the return value.")
386    
387     (definterface who-specializes (class-name)
388     "Return the locations where CLASS-NAME (a symbol) is specialized.
389     See WHO-CALLS for a description of the return value.")
390    
391     ;;; Simpler variants.
392    
393     (definterface list-callers (function-name)
394     "List the callers of FUNCTION-NAME.
395     This function is like WHO-CALLS except that it is expected to use
396     lower-level means. Whereas WHO-CALLS is usually implemented with
397     special compiler support, LIST-CALLERS is usually implemented by
398     groveling for constants in function objects throughout the heap.
399    
400     The return value is as for WHO-CALLS.")
401    
402     (definterface list-callees (function-name)
403     "List the functions called by FUNCTION-NAME.
404     See LIST-CALLERS for a description of the return value.")
405    
406    
407 heller 1.23 ;;;; Profiling
408    
409     ;;; The following functions define a minimal profiling interface.
410    
411     (definterface profile (fname)
412     "Marks symbol FNAME for profiling.")
413    
414     (definterface profiled-functions ()
415     "Returns a list of profiled functions.")
416    
417     (definterface unprofile (fname)
418     "Marks symbol FNAME as not profiled.")
419    
420     (definterface unprofile-all ()
421     "Marks all currently profiled functions as not profiled."
422     (dolist (f (profiled-functions))
423     (unprofile f)))
424    
425     (definterface profile-report ()
426     "Prints profile report.")
427    
428     (definterface profile-reset ()
429     "Resets profile counters.")
430    
431     (definterface profile-package (package callers-p methods)
432     "Wrap profiling code around all functions in PACKAGE. If a function
433     is already profiled, then unprofile and reprofile (useful to notice
434     function redefinition.)
435    
436     If CALLERS-P is T names have counts of the most common calling
437     functions recorded.
438    
439     When called with arguments :METHODS T, profile all methods of all
440     generic functions having names in the given package. Generic functions
441     themselves, that is, their dispatch functions, are left alone.")
442    
443    
444 heller 1.19 ;;;; Inspector
445    
446 heller 1.35 (definterface inspected-parts (object)
447     "Return a short description and a list of (LABEL . VALUE) pairs."
448     (values (format nil "~S is an atom." object) '()))
449 heller 1.19
450 heller 1.29 (definterface describe-primitive-type (object)
451 heller 1.35 "Return a string describing the primitive type of object."
452 heller 1.36 (declare (ignore object))
453 heller 1.35 "N/A")
454 heller 1.19
455    
456 heller 1.36 ;;;; Multithreading
457 lgorrie 1.21 ;;;
458     ;;; The default implementations are sufficient for non-multiprocessing
459     ;;; implementations.
460 lgorrie 1.9
461 lgorrie 1.21 (definterface startup-multiprocessing ()
462 lgorrie 1.9 "Initialize multiprocessing, if necessary.
463    
464     This function is called directly through the listener, not in an RPC
465     from Emacs. This is to support interfaces such as CMUCL's
466     MP::STARTUP-IDLE-AND-TOP-LEVEL-LOOPS which does not return like a
467 lgorrie 1.21 normal function."
468     nil)
469 lgorrie 1.9
470 lgorrie 1.21 (definterface spawn (fn &key name)
471     "Create a new thread to call FN.")
472 lgorrie 1.17
473 heller 1.28 (definterface thread-name (thread)
474     "Return the name of THREAD.
475 lgorrie 1.9
476     Thread names are be single-line strings and are meaningful to the
477 lgorrie 1.21 user. They do not have to be unique."
478 heller 1.28 (declare (ignore thread))
479 lgorrie 1.21 "The One True Thread")
480 lgorrie 1.9
481 heller 1.28 (definterface thread-status (thread)
482     "Return a string describing THREAD's state."
483     (declare (ignore thread))
484     "")
485    
486 lgorrie 1.21 (definterface make-lock (&key name)
487 lgorrie 1.17 "Make a lock for thread synchronization.
488 lgorrie 1.21 Only one thread may hold the lock (via CALL-WITH-LOCK-HELD) at a time."
489 heller 1.23 (declare (ignore name))
490 lgorrie 1.21 :null-lock)
491 lgorrie 1.9
492 lgorrie 1.21 (definterface call-with-lock-held (lock function)
493     "Call FUNCTION with LOCK held, queueing if necessary."
494 heller 1.24 (declare (ignore lock)
495     (type function function))
496 lgorrie 1.21 (funcall function))
497 heller 1.25
498     (definterface current-thread ()
499     "Return the currently executing thread."
500     0)
501 heller 1.28
502     (definterface all-threads ()
503     "Return a list of all threads.")
504    
505     (definterface thread-alive-p (thread)
506 heller 1.35 "Test if THREAD is termintated."
507     (member thread (all-threads)))
508 heller 1.25
509     (definterface interrupt-thread (thread fn)
510     "Cause THREAD to execute FN.")
511    
512 mbaringer 1.34 (definterface kill-thread (thread)
513     "Kill THREAD."
514     (declare (ignore thread))
515     nil)
516    
517 heller 1.25 (definterface send (thread object)
518     "Send OBJECT to thread THREAD.")
519    
520     (definterface receive ()
521     "Return the next message from current thread's mailbox.")

  ViewVC Help
Powered by ViewVC 1.1.5