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

Contents of /slime/swank-backend.lisp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations)
Thu Jan 29 08:37:57 2004 UTC (10 years, 2 months ago) by heller
Branch: MAIN
Changes since 1.22: +45 -0 lines
Profiler support.  Patch by Michael Weber.
1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil; outline-regexp: ";;;;;*" -*-
2 ;;;
3 ;;; slime-backend.lisp --- SLIME backend interface.
4 ;;;
5 ;;; Created by James Bielman in 2003. Released into the public domain.
6 ;;;
7 ;;; 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
11 (defpackage :swank
12 (:use :common-lisp)
13 (:nicknames #:swank-backend)
14 (: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 #:compiler-notes-for-emacs
21 #:completions
22 #:create-server
23 #:create-swank-server
24 #:describe-definition
25 #:describe-symbol
26 #:describe-symbol-for-emacs
27 #:disassemble-symbol
28 #:documentation-symbol
29 #:eval-in-frame
30 #:return-from-frame
31 #:restart-frame
32 #:eval-string
33 #:eval-string-in-frame
34 #:find-function-locations
35 #:frame-catch-tags
36 #:frame-locals
37 #:frame-source-location-for-emacs
38 #:frame-source-position
39 #:getpid
40 #:give-goahead
41 #:give-gohead
42 #:init-inspector
43 #:inspect-in-frame
44 #:inspect-nth-part
45 #:inspector-next
46 #:inspector-pop
47 #:interactive-eval
48 #:interactive-eval-region
49 #:invoke-nth-restart
50 #:invoke-nth-restart-for-emacs
51 #:list-all-package-names
52 #:list-callees
53 #:list-callers
54 #:listener-eval
55 #:load-file
56 #:pprint-eval
57 #:pprint-eval-string-in-frame
58 #:quit-inspector
59 #:re-evaluate-defvar
60 #:set-default-directory
61 #:set-package
62 #:sldb-abort
63 #:sldb-break-with-default-debugger
64 #:sldb-continue
65 #:slime-debugger-function
66 #:start-server
67 #:startup-multiprocessing
68 #:startup-multiprocessing-for-emacs
69 #:swank-compile-file
70 #:swank-compile-string
71 #:swank-macroexpand
72 #:swank-macroexpand-1
73 #:swank-macroexpand-all
74 #:take-input
75 #:thread-id
76 #:thread-name
77 #:throw-to-toplevel
78 #:toggle-trace-fdefinition
79 #:untrace-all
80 #:profile
81 #:unprofile
82 #:unprofile-all
83 #:profiled-functions
84 #:profile-report
85 #:profile-reset
86 #:profile-package
87 #:wait-goahead
88 #:warn-unimplemented-interfaces
89 #:who-binds
90 #:who-calls
91 #:who-macroexpands
92 #:who-references
93 #:who-sets
94 ))
95
96 (in-package :swank)
97
98
99 ;;;; Metacode
100
101 (defparameter *interface-functions* '()
102 "The names of all interface functions.")
103
104 (defparameter *unimplemented-interfaces* '()
105 "List of interface functions that are not implemented.
106 DEFINTERFACE adds to this list and DEFIMPLEMENTATION removes.")
107
108 (defmacro definterface (name args documentation &body default-body)
109 "Define an interface function for the backend to implement.
110 A generic function is defined with NAME, ARGS, and DOCUMENTATION.
111
112 If a DEFAULT-BODY is supplied then NO-APPLICABLE-METHOD is specialized
113 to execute the body if the backend doesn't provide a specific
114 implementation.
115
116 Backends implement these functions using DEFIMPLEMENTATION."
117 (flet ((gen-default-impl ()
118 (let ((received-args (gensym "ARGS-")))
119 `(defmethod no-applicable-method ((#:method
120 (eql (function ,name)))
121 &rest ,received-args)
122 (destructuring-bind ,args ,received-args
123 ,@default-body)))))
124 `(prog1 (defgeneric ,name ,args (:documentation ,documentation))
125 (pushnew ',name *interface-functions*)
126 ,(if (null default-body)
127 `(pushnew ',name *unimplemented-interfaces*)
128 (gen-default-impl)))))
129
130 (defmacro defimplementation (name args &body body)
131 ;; Is this a macro no-no -- should it be pushed out of macroexpansion?
132 `(prog1 (defmethod ,name ,args ,@body)
133 (if (member ',name *interface-functions*)
134 (setq *unimplemented-interfaces*
135 (remove ',name *unimplemented-interfaces*))
136 (warn "DEFIMPLEMENTATION of undefined interface (~S)" ',name))))
137
138 (defun warn-unimplemented-interfaces ()
139 "Warn the user about unimplemented backend features.
140 The portable code calls this function at startup."
141 (warn "These Swank interfaces are unimplemented:~% ~A"
142 (sort (copy-list *unimplemented-interfaces*) #'string<)))
143
144
145 ;;;; TCP server
146
147 (definterface create-socket (port)
148 "Create a listening TCP socket on port PORT.")
149
150 (definterface local-port (socket)
151 "Return the local port number of SOCKET.")
152
153 (definterface close-socket (socket)
154 "Close the socket SOCKET.")
155
156 (definterface accept-connection (socket)
157 "Accept a client connection on the listening socket SOCKET. Return
158 a stream for the new connection.")
159
160 (definterface add-input-handler (socket fn)
161 "Call FN whenever SOCKET is readable.")
162
163 (definterface remove-input-handlers (socket)
164 "Remove all input handlers for SOCKET.")
165
166 ;;; Base condition for networking errors.
167 (define-condition network-error (error) ())
168
169 (definterface emacs-connected ()
170 "Hook called when the first connection from Emacs is established.
171 Called from the INIT-FN of the socket server that accepts the
172 connection.
173
174 This is intended for setting up extra context, e.g. to discover
175 that the calling thread is the one that interacts with Emacs."
176 nil)
177
178
179 ;;;; Unix signals
180
181 (defconstant +sigint+ 2)
182
183 (defgeneric call-without-interrupts (fn)
184 (:documentation "Call FN in a context where interrupts are disabled."))
185
186 (defgeneric getpid ()
187 (:documentation "Return the (Unix) process ID of this superior Lisp."))
188
189
190 ;;;; Compilation
191
192 (definterface call-with-compilation-hooks (func)
193 "Call FUNC with hooks to trigger SLDB on compiler errors.")
194
195 (defmacro with-compilation-hooks ((&rest ignore) &body body)
196 (declare (ignore ignore))
197 `(call-with-compilation-hooks (lambda () (progn ,@body))))
198
199 (definterface compile-string-for-emacs (string &key buffer position)
200 "Compile source from STRING. During compilation, compiler
201 conditions must be trapped and resignalled as COMPILER-CONDITIONs.
202
203 If supplied, BUFFER and POSITION specify the source location in Emacs.
204
205 Additionally, if POSITION is supplied, it must be added to source
206 positions reported in compiler conditions.")
207
208 (definterface compile-file-for-emacs (filename load-p)
209 "Compile FILENAME signalling COMPILE-CONDITIONs.
210 If LOAD-P is true, load the file after compilation.")
211
212 (deftype severity () '(member :error :warning :style-warning :note))
213
214 ;; Base condition type for compiler errors, warnings and notes.
215 (define-condition compiler-condition (condition)
216 ((original-condition
217 ;; The original condition thrown by the compiler if appropriate.
218 ;; May be NIL if a compiler does not report using conditions.
219 :type (or null condition)
220 :initarg :original-condition
221 :accessor original-condition)
222
223 (severity :type severity
224 :initarg :severity
225 :accessor severity)
226
227 (message :initarg :message
228 :accessor message)
229
230 (location :initarg :location
231 :accessor location)))
232
233
234 ;;;; Streams
235
236 (definterface make-fn-streams (input-fn output-fn)
237 "Return character input and output streams backended by functions.
238 When input is needed, INPUT-FN is called with no arguments to
239 return a string.
240 When output is ready, OUTPUT-FN is called with the output as its
241 argument.
242
243 Output should be forced to OUTPUT-FN before calling INPUT-FN.
244
245 The streams are returned as two values.")
246
247
248 ;;;; Documentation
249
250 (definterface arglist-string (function-name)
251 "Return the argument for FUNCTION-NAME as a string.
252 The result should begin and end with parenthesis.")
253
254 (definterface macroexpand-all (form)
255 "Recursively expand all macros in FORM.
256 Return the resulting form.")
257
258 (definterface describe-symbol-for-emacs (symbol)
259 "Return a property list describing SYMBOL.
260
261 The property list has an entry for each interesting aspect of the
262 symbol. The recognised keys are:
263
264 :VARIABLE :FUNCTION :SETF :TYPE :CLASS :MACRO :COMPILER-MACRO
265 :ALIEN-TYPE :ALIEN-STRUCT :ALIEN-UNION :ALIEN-ENUM
266
267 The value of each property is the corresponding documentation string,
268 or :NOT-DOCUMENTED. It is legal to include keys not listed here.
269
270 Properties should be included if and only if they are applicable to
271 the symbol. For example, only (and all) fbound symbols should include
272 the :FUNCTION property.
273
274 Example:
275 \(describe-symbol-for-emacs 'vector)
276 => (:CLASS :NOT-DOCUMENTED
277 :TYPE :NOT-DOCUMENTED
278 :FUNCTION \"Constructs a simple-vector from the given objects.\")")
279
280 (definterface describe-definition (name type)
281 "Describe the definition NAME of TYPE.
282 TYPE can be any value returned by DESCRIBE-SYMBOL-FOR-EMACS.
283
284 Return a documentation string, or NIL if none is available.")
285
286
287 ;;;; Debugging
288
289 (definterface call-with-debugging-environment (debugger-loop-fn)
290 "Call DEBUGGER-LOOP-FN in a suitable debugging environment.
291
292 This function is called recursively at each debug level to invoke the
293 debugger loop. The purpose is to setup any necessary environment for
294 other debugger callbacks that will be called within the debugger loop.
295
296 For example, this is a reasonable place to compute a backtrace, switch
297 to safe reader/printer settings, and so on.")
298
299 (define-condition sldb-condition (condition)
300 ((original-condition
301 :initarg :original-condition
302 :accessor original-condition))
303 (:documentation
304 "Wrapper for conditions that should not be debugged.
305
306 When a condition arises from the internals of the debugger, it is not
307 desirable to debug it -- we'd risk entering an endless loop trying to
308 debug the debugger! Instead, such conditions can be reported to the
309 user without (re)entering the debugger by wrapping them as
310 `sldb-condition's."))
311
312 (definterface debugger-info-for-emacs (start end)
313 "Return debugger state, with stack frames from START to END.
314 The result is a list:
315 (condition ({restart}*) ({stack-frame}*)
316 where
317 condition ::= (description type)
318 restart ::= (name description)
319 stack-frame ::= (number description)
320
321 condition---a pair of strings: message, and type.
322
323 restart---a pair of strings: restart name, and description.
324
325 stack-frame---a number from zero (the top), and a printed
326 representation of the frame's call.
327
328 Below is an example return value. In this case the condition was a
329 division by zero (multi-line description), and only one frame is being
330 fetched (start=0, end=1).
331
332 ((\"Arithmetic error DIVISION-BY-ZERO signalled.
333 Operation was KERNEL::DIVISION, operands (1 0).\"
334 \"[Condition of type DIVISION-BY-ZERO]\")
335 ((\"ABORT\" \"Return to Slime toplevel.\")
336 (\"ABORT\" \"Return to Top-Level.\"))
337 ((0 \"(KERNEL::INTEGER-/-INTEGER 1 0)\")))")
338
339 (definterface backtrace (start end)
340 "Return a list containing a backtrace of the condition current
341 being debugged. The results are unspecified if this function is
342 called outside the dynamic contour of a debugger hook defined by
343 DEFINE-DEBUGGER-HOOK.
344
345 START and END are zero-based indices constraining the number of
346 frames returned. Frame zero is defined as the frame which invoked
347 the debugger.
348
349 The backtrace is returned as a list of tuples of the form
350 \(FRAME-NUMBER FRAME-DESCRIPTION), where FRAME-NUMBER is the
351 index of the frame, defined like START/END, and FRAME-DESCRIPTION
352 is a string containing text to display in the debugger for this
353 frame.
354
355 An example return value:
356
357 ((0 \"(HELLO \"world\")\")
358 (1 \"(RUN-EXCITING-LISP-DEMO)\")
359 (2 \"(SYS::%TOPLEVEL #<SYS::ENVIRONMENT #x394834>)\"))")
360
361 (definterface frame-source-location-for-emacs (frame-number)
362 "Return the source location for FRAME-NUMBER.")
363
364 (definterface frame-catch-tags (frame-number)
365 "Return a list of XXX list of what? catch tags for a debugger
366 stack frame. The results are undefined unless this is called
367 within the dynamic contour of a function defined by
368 DEFINE-DEBUGGER-HOOK.")
369
370 (definterface frame-locals (frame-number)
371 "Return a list of XXX local variable designators define me
372 for a debugger stack frame. The results are undefined unless
373 this is called within the dynamic contour of a function defined
374 by DEFINE-DEBUGGER-HOOK.")
375
376 (definterface eval-in-frame (form frame-number)
377 "Evaluate a Lisp form in the lexical context of a stack frame
378 in the debugger. The results are undefined unless called in the
379 dynamic contour of a function defined by DEFINE-DEBUGGER-HOOK.
380
381 FRAME-NUMBER must be a positive integer with 0 indicating the
382 frame which invoked the debugger.
383
384 The return value is the result of evaulating FORM in the
385 appropriate context.")
386
387 (definterface return-from-frame (frame-number form)
388 "Unwind the stack to the frame FRAME-NUMBER and return the value(s)
389 produced by evaluating FORM in the frame context to its caller.
390
391 Execute any clean-up code from unwind-protect forms above the frame
392 during unwinding.
393
394 Return a string describing the error if it's not possible to return
395 from the frame.")
396
397 (definterface restart-frame (frame-number)
398 "Restart execution of the frame FRAME-NUMBER with the same arguments
399 as it was called originally.")
400
401
402 ;;;; Profiling
403
404 ;;; The following functions define a minimal profiling interface.
405
406 (definterface profile (fname)
407 "Marks symbol FNAME for profiling.")
408
409 (definterface profiled-functions ()
410 "Returns a list of profiled functions.")
411
412 (definterface unprofile (fname)
413 "Marks symbol FNAME as not profiled.")
414
415 (definterface unprofile-all ()
416 "Marks all currently profiled functions as not profiled."
417 (dolist (f (profiled-functions))
418 (unprofile f)))
419
420 (definterface profile-report ()
421 "Prints profile report.")
422
423 (definterface profile-reset ()
424 "Resets profile counters.")
425
426 (definterface profile-package (package callers-p methods)
427 "Wrap profiling code around all functions in PACKAGE. If a function
428 is already profiled, then unprofile and reprofile (useful to notice
429 function redefinition.)
430
431 If CALLERS-P is T names have counts of the most common calling
432 functions recorded.
433
434 When called with arguments :METHODS T, profile all methods of all
435 generic functions having names in the given package. Generic functions
436 themselves, that is, their dispatch functions, are left alone.")
437
438
439 ;;;; Queries
440
441 #+(or)
442 ;;; This is probably a better interface than find-function-locations.
443 (definterface find-definitions (name)
444 "Return a list of (LABEL . LOCATION) pairs for NAME's definitions.
445
446 NAME is string denoting a symbol or \"definition specifier\".
447
448 LABEL is a string describing the definition, e.g., \"foo\" or
449 \"(method foo (string number))\" or \"(variable bar)\".
450
451 LOCATION is a source location of the form:
452
453 <location> ::= (:location <buffer> <position>)
454 | (:error <message>)
455
456 <buffer> ::= (:file <filename>)
457 | (:buffer <buffername>)
458 | (:source-form <string>)
459
460 <position> ::= (:position <fixnum> [<align>]) ; 1 based
461 | (:function-name <string>)
462 ")
463
464 (definterface find-function-locations (name)
465 "Return a list (LOCATION LOCATION ...) for NAME's definitions.
466
467 LOCATION is a source location of the form:
468
469 <location> ::= (:location <buffer> <position>)
470 | (:error <message>)
471
472 <buffer> ::= (:file <filename>)
473 | (:buffer <buffername>)
474 | (:source-form <string>)
475
476 <position> ::= (:position <fixnum> [<align>]) ; 1 based
477 | (:line <fixnum> [<fixnum>])
478 | (:function-name <string>)
479 | (:source-path <list> <start-position>)
480 ")
481
482
483 ;;;; Inspector
484
485 (defgeneric inspected-parts (object)
486 (:documentation
487 "Return a short description and a list of (LABEL . VALUE) pairs."))
488
489 (defgeneric describe-primitive-type (object)
490 (:documentation
491 "Return a string describing the primitive type of object."))
492
493
494 ;;;; Multiprocessing
495 ;;;
496 ;;; The default implementations are sufficient for non-multiprocessing
497 ;;; implementations.
498
499 (definterface startup-multiprocessing ()
500 "Initialize multiprocessing, if necessary.
501
502 This function is called directly through the listener, not in an RPC
503 from Emacs. This is to support interfaces such as CMUCL's
504 MP::STARTUP-IDLE-AND-TOP-LEVEL-LOOPS which does not return like a
505 normal function."
506 nil)
507
508 (definterface spawn (fn &key name)
509 "Create a new thread to call FN.")
510
511 (definterface thread-id ()
512 "Return a value that uniquely identifies the current thread.
513 Thread-IDs allow Emacs to refer to individual threads.
514
515 When called several times by the same thread, all return values are
516 EQUAL. The value has a READable printed representation that preserves
517 equality. The printed representation must be identical in Emacs Lisp
518 and Common Lisp, and short enough to include in the REPL prompt.
519
520 For example, a THREAD-ID could be an integer or a short ASCII string.
521
522 Systems that do not support multiprocessing return NIL."
523 nil)
524
525 (definterface thread-name (thread-id)
526 "Return the name of the thread identified by THREAD-ID.
527
528 Thread names are be single-line strings and are meaningful to the
529 user. They do not have to be unique."
530 (declare (ignore thread-id))
531 "The One True Thread")
532
533 (definterface make-lock (&key name)
534 "Make a lock for thread synchronization.
535 Only one thread may hold the lock (via CALL-WITH-LOCK-HELD) at a time."
536 (declare (ignore name))
537 :null-lock)
538
539 (definterface call-with-lock-held (lock function)
540 "Call FUNCTION with LOCK held, queueing if necessary."
541 (declare (ignore lock))
542 (funcall function))
543
544
545 ;;;; XREF
546
547 (definterface who-calls (function-name)
548 "Return the call sites of FUNCTION-NAME (a string).
549 The results are grouped together by filename:
550 <result> ::= (<file>*)
551 <file> ::= (<filename> . (<reference>*))
552 <reference> ::= (<label> . <location>)
553 <label> ::= string
554 <location> ::= source-location")
555
556 (definterface who-references (variable-name)
557 "Return the locations where VARIABLE-NAME (a string) is referenced.
558 See WHO-CALLS for a description of the return value.")
559
560 (definterface who-binds (variable-name)
561 "Return the locations where VARIABLE-NAME (a string) is bound.
562 See WHO-CALLS for a description of the return value.")
563
564 (definterface who-sets (variable-name)
565 "Return the locations where VARIABLE-NAME (a string) is set.
566 See WHO-CALLS for a description of the return value.")
567
568 (definterface who-macroexpands (macro-name)
569 "Return the locations where MACRO-NAME (a string) is expanded.
570 See WHO-CALLS for a description of the return value.")
571
572 (definterface who-specializes (class-name)
573 "Return the locations where CLASS-NAME (a string) is specialized.
574 See WHO-CALLS for a description of the return value.")
575
576 ;;; Simpler variants.
577
578 (definterface list-callers (function-name)
579 "List the callers of FUNCTION-NAME.
580 This function is like WHO-CALLS except that it is expected to use
581 lower-level means. Whereas WHO-CALLS is usually implemented with
582 special compiler support, LIST-CALLERS is usually implemented by
583 groveling for constants in function objects throughout the heap.
584
585 The return value is as for WHO-CALLS.")
586
587 (definterface list-callees (function-name)
588 "List the functions called by FUNCTION-NAME.
589 See LIST-CALLERS for a description of the return value.")
590

  ViewVC Help
Powered by ViewVC 1.1.5