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

Contents of /slime/swank-backend.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.20 - (hide annotations)
Sun Jan 18 07:15:49 2004 UTC (10 years, 3 months ago) by heller
Branch: MAIN
Changes since 1.19: +11 -0 lines
(arglist-string): Refactor common code to swank.lisp.

(call-without-interrupts, getpid): Are now generic functions.
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 heller 1.20 ;;;; Unix signals
136    
137     (defconstant +sigint+ 2)
138    
139     (defgeneric call-without-interrupts (fn)
140     (:documentation "Call FN in a context where interrupts are disabled."))
141    
142     (defgeneric getpid ()
143     (:documentation "Return the (Unix) process ID of this superior Lisp."))
144    
145    
146 lgorrie 1.1 ;;;; Compilation
147 dbarlow 1.8
148     (defgeneric call-with-compilation-hooks (func)
149     (:documentation
150     "Call FUNC with hooks to trigger SLDB on compiler errors."))
151 lgorrie 1.13
152 vsedach 1.14 (defmacro with-compilation-hooks ((&rest ignore) &body body)
153     (declare (ignore ignore))
154 dbarlow 1.8 `(call-with-compilation-hooks (lambda () (progn ,@body))))
155 lgorrie 1.1
156     (defgeneric compile-string-for-emacs (string &key buffer position)
157     (:documentation
158     "Compile source from STRING. During compilation, compiler
159     conditions must be trapped and resignalled as COMPILER-CONDITIONs.
160    
161     If supplied, BUFFER and POSITION specify the source location in Emacs.
162    
163     Additionally, if POSITION is supplied, it must be added to source
164     positions reported in compiler conditions."))
165    
166     (defgeneric compile-file-for-emacs (filename load-p)
167     (:documentation
168     "Compile FILENAME signalling COMPILE-CONDITIONs.
169     If LOAD-P is true, load the file after compilation."))
170    
171 lgorrie 1.13 (deftype severity () '(member :error :warning :style-warning :note))
172    
173     ;; Base condition type for compiler errors, warnings and notes.
174     (define-condition compiler-condition (condition)
175     ((original-condition
176     ;; The original condition thrown by the compiler if appropriate.
177     ;; May be NIL if a compiler does not report using conditions.
178     :type (or null condition)
179     :initarg :original-condition
180     :accessor original-condition)
181    
182     (severity :type severity
183     :initarg :severity
184     :accessor severity)
185    
186     (message :initarg :message
187     :accessor message)
188    
189     (location :initarg :location
190     :accessor location)))
191    
192 lgorrie 1.17
193 lgorrie 1.13 ;;;; Streams
194    
195     (defgeneric make-fn-streams (input-fn output-fn)
196     (:documentation
197     "Return character input and output streams backended by functions.
198     When input is needed, INPUT-FN is called with no arguments to
199     return a string.
200     When output is ready, OUTPUT-FN is called with the output as its
201     argument.
202    
203     Output should be forced to OUTPUT-FN before calling INPUT-FN.
204    
205     The streams are returned as two values."))
206    
207 lgorrie 1.1
208     ;;;; Documentation
209    
210     (defgeneric arglist-string (function-name)
211     (:documentation
212     "Return the argument for FUNCTION-NAME as a string.
213     The result should begin and end with parenthesis."))
214    
215     (defgeneric macroexpand-all (form)
216     (:documentation
217     "Recursively expand all macros in FORM.
218     Return the resulting form."))
219    
220     (defgeneric describe-symbol-for-emacs (symbol)
221     (:documentation
222     "Return a property list describing SYMBOL.
223    
224     The property list has an entry for each interesting aspect of the
225     symbol. The recognised keys are:
226    
227     :VARIABLE :FUNCTION :SETF :TYPE :CLASS :MACRO :COMPILER-MACRO
228     :ALIEN-TYPE :ALIEN-STRUCT :ALIEN-UNION :ALIEN-ENUM
229    
230     The value of each property is the corresponding documentation string,
231     or :NOT-DOCUMENTED. It is legal to include keys not listed here.
232    
233     Properties should be included if and only if they are applicable to
234     the symbol. For example, only (and all) fbound symbols should include
235     the :FUNCTION property.
236    
237     Example:
238     \(describe-symbol-for-emacs 'vector)
239     => (:CLASS :NOT-DOCUMENTED
240     :TYPE :NOT-DOCUMENTED
241     :FUNCTION \"Constructs a simple-vector from the given objects.\")"))
242 lgorrie 1.2
243    
244     ;;;; Debugging
245    
246     (defgeneric call-with-debugging-environment (debugger-loop-fn)
247     (:documentation
248     "Call DEBUGGER-LOOP-FN in a suitable debugging environment.
249    
250     This function is called recursively at each debug level to invoke the
251     debugger loop. The purpose is to setup any necessary environment for
252     other debugger callbacks that will be called within the debugger loop.
253    
254     For example, this is a reasonable place to compute a backtrace, switch
255     to safe reader/printer settings, and so on."))
256    
257     (define-condition sldb-condition (condition)
258     ((original-condition
259     :initarg :original-condition
260 heller 1.5 :accessor original-condition))
261 lgorrie 1.2 (:documentation
262     "Wrapper for conditions that should not be debugged.
263    
264     When a condition arises from the internals of the debugger, it is not
265     desirable to debug it -- we'd risk entering an endless loop trying to
266     debug the debugger! Instead, such conditions can be reported to the
267     user without (re)entering the debugger by wrapping them as
268     `sldb-condition's."))
269    
270     (defgeneric debugger-info-for-emacs (start end)
271     (:documentation
272     "Return debugger state, with stack frames from START to END.
273     The result is a list:
274 heller 1.12 (condition ({restart}*) ({stack-frame}*)
275 lgorrie 1.2 where
276 heller 1.12 condition ::= (description type)
277 lgorrie 1.2 restart ::= (name description)
278     stack-frame ::= (number description)
279    
280 heller 1.12 condition---a pair of strings: message, and type.
281 lgorrie 1.2
282     restart---a pair of strings: restart name, and description.
283    
284     stack-frame---a number from zero (the top), and a printed
285     representation of the frame's call.
286    
287     Below is an example return value. In this case the condition was a
288     division by zero (multi-line description), and only one frame is being
289     fetched (start=0, end=1).
290    
291 heller 1.12 ((\"Arithmetic error DIVISION-BY-ZERO signalled.
292     Operation was KERNEL::DIVISION, operands (1 0).\"
293     \"[Condition of type DIVISION-BY-ZERO]\")
294 lgorrie 1.2 ((\"ABORT\" \"Return to Slime toplevel.\")
295     (\"ABORT\" \"Return to Top-Level.\"))
296 heller 1.12 ((0 \"(KERNEL::INTEGER-/-INTEGER 1 0)\")))"))
297 lgorrie 1.1
298 lgorrie 1.3 (defgeneric backtrace (start end)
299     (:documentation
300     "Return a list containing a backtrace of the condition current
301     being debugged. The results are unspecified if this function is
302     called outside the dynamic contour of a debugger hook defined by
303     DEFINE-DEBUGGER-HOOK.
304    
305     START and END are zero-based indices constraining the number of
306     frames returned. Frame zero is defined as the frame which invoked
307     the debugger.
308    
309     The backtrace is returned as a list of tuples of the form
310     \(FRAME-NUMBER FRAME-DESCRIPTION), where FRAME-NUMBER is the
311     index of the frame, defined like START/END, and FRAME-DESCRIPTION
312     is a string containing text to display in the debugger for this
313     frame.
314    
315     An example return value:
316    
317     ((0 \"(HELLO \"world\")\")
318     (1 \"(RUN-EXCITING-LISP-DEMO)\")
319     (2 \"(SYS::%TOPLEVEL #<SYS::ENVIRONMENT #x394834>)\"))"))
320    
321     (defgeneric frame-source-location-for-emacs (frame-number)
322     (:documentation
323     "Return the source location for FRAME-NUMBER."))
324    
325     (defgeneric frame-catch-tags (frame-number)
326     (:documentation
327     "Return a list of XXX list of what? catch tags for a debugger
328     stack frame. The results are undefined unless this is called
329     within the dynamic contour of a function defined by
330     DEFINE-DEBUGGER-HOOK."))
331    
332     (defgeneric frame-locals (frame-number)
333     (:documentation
334     "Return a list of XXX local variable designators define me
335     for a debugger stack frame. The results are undefined unless
336     this is called within the dynamic contour of a function defined
337     by DEFINE-DEBUGGER-HOOK."))
338    
339     (defgeneric eval-in-frame (form frame-number)
340     (:documentation
341     "Evaluate a Lisp form in the lexical context of a stack frame
342     in the debugger. The results are undefined unless called in the
343     dynamic contour of a function defined by DEFINE-DEBUGGER-HOOK.
344    
345     FRAME-NUMBER must be a positive integer with 0 indicating the
346     frame which invoked the debugger.
347    
348     The return value is the result of evaulating FORM in the
349     appropriate context."))
350    
351    
352     ;;;; Queries
353    
354 heller 1.7 #+(or)
355     ;;; This is probably a better interface than find-function-locations.
356     (defgeneric find-definitions (name)
357 lgorrie 1.3 (:documentation
358 heller 1.7 "Return a list of (LABEL . LOCATION) pairs for NAME's definitions.
359 lgorrie 1.3
360 heller 1.7 NAME is string denoting a symbol or \"definition specifier\".
361    
362     LABEL is a string describing the definition, e.g., \"foo\" or
363     \"(method foo (string number))\" or \"(variable bar)\".
364    
365     LOCATION is a source location of the form:
366    
367     <location> ::= (:location <buffer> <position>)
368     | (:error <message>)
369    
370     <buffer> ::= (:file <filename>)
371     | (:buffer <buffername>)
372     | (:source-form <string>)
373    
374     <position> ::= (:position <fixnum> [<align>]) ; 1 based
375     | (:function-name <string>)
376     "))
377    
378     (defgeneric find-function-locations (name)
379     (:documentation
380     "Return a list (LOCATION LOCATION ...) for NAME's definitions.
381    
382     LOCATION is a source location of the form:
383    
384     <location> ::= (:location <buffer> <position>)
385     | (:error <message>)
386    
387     <buffer> ::= (:file <filename>)
388     | (:buffer <buffername>)
389     | (:source-form <string>)
390    
391     <position> ::= (:position <fixnum> [<align>]) ; 1 based
392 heller 1.12 | (:line <fixnum> [<fixnum>])
393     | (:function-name <string>)
394     | (:source-path <list> <start-position>)
395     "))
396 lgorrie 1.9
397    
398 heller 1.19 ;;;; Inspector
399    
400     (defgeneric inspected-parts (object)
401     (:documentation
402     "Return a short description and a list of (LABEL . VALUE) pairs."))
403    
404     (defgeneric describe-primitive-type (object)
405     (:documentation
406     "Return a string describing the primitive type of object."))
407    
408    
409 lgorrie 1.9 ;;;; Multiprocessing
410    
411     (defgeneric startup-multiprocessing ()
412     (:documentation
413     "Initialize multiprocessing, if necessary.
414    
415     This function is called directly through the listener, not in an RPC
416     from Emacs. This is to support interfaces such as CMUCL's
417     MP::STARTUP-IDLE-AND-TOP-LEVEL-LOOPS which does not return like a
418     normal function."))
419    
420 lgorrie 1.17 (defgeneric spawn (fn &key name)
421     (:documentation "Create a new thread to call FN."))
422    
423 lgorrie 1.9 (defgeneric thread-id ()
424     (:documentation
425     "Return a value that uniquely identifies the current thread.
426     Thread-IDs allow Emacs to refer to individual threads.
427    
428     When called several times by the same thread, all return values are
429     EQUAL. The value has a READable printed representation that preserves
430     equality. The printed representation must be identical in Emacs Lisp
431     and Common Lisp, and short enough to include in the REPL prompt.
432    
433     For example, a THREAD-ID could be an integer or a short ASCII string.
434    
435     Systems that do not support multiprocessing return NIL."))
436    
437     (defgeneric thread-name (thread-id)
438     (:documentation
439     "Return the name of the thread identified by THREAD-ID.
440    
441     Thread names are be single-line strings and are meaningful to the
442     user. They do not have to be unique."))
443    
444 lgorrie 1.17 (defgeneric make-lock (&key name)
445 lgorrie 1.9 (:documentation
446 lgorrie 1.17 "Make a lock for thread synchronization.
447     Only one thread may hold the lock (via CALL-WITH-LOCK-HELD) at a time."))
448 lgorrie 1.9
449 lgorrie 1.17 (defgeneric call-with-lock-held (lock function)
450 lgorrie 1.9 (:documentation
451 lgorrie 1.17 "Call FUNCTION with LOCK held, queueing if necessary."))
452 lgorrie 1.9
453 lgorrie 1.13
454 lgorrie 1.9 ;;;;; Default implementation for non-MP systems
455    
456     ;;; Using NO-APPLICABLE-METHOD to supply a default implementation that
457     ;;; works in systems that don't have multiprocessing.
458     ;;; (Good or bad idea? -luke)
459    
460     (defmethod no-applicable-method ((m (eql #'startup-multiprocessing)) &rest _)
461 lgorrie 1.13 (declare (ignore _))
462 lgorrie 1.9 nil)
463     (defmethod no-applicable-method ((m (eql #'thread-id)) &rest _)
464 lgorrie 1.13 (declare (ignore _))
465 lgorrie 1.9 nil)
466     (defmethod no-applicable-method ((m (eql #'thread-name)) &rest _)
467 lgorrie 1.13 (declare (ignore _))
468 lgorrie 1.9 "The One True Thread")
469 lgorrie 1.17 (defmethod no-applicable-method ((m (eql #'make-lock)) &rest _)
470 lgorrie 1.13 (declare (ignore _))
471 lgorrie 1.17 :null-lock)
472     (defmethod no-applicable-method ((m (eql #'call-with-lock-held)) &rest args)
473     (funcall (second args)))
474 lgorrie 1.1

  ViewVC Help
Powered by ViewVC 1.1.5