1 ;;;; This file contains functions that hack on the global function
2 ;;;; namespace (primarily concerned with SETF functions here). Also,
3 ;;;; function encapsulation and routines that set and return
4 ;;;; definitions disregarding whether they might be encapsulated.
6 ;;;; This software is part of the SBCL system. See the README file for
9 ;;;; This software is derived from the CMU CL system, which was
10 ;;;; written at Carnegie Mellon University and released into the
11 ;;;; public domain. The software is in the public domain and is
12 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
13 ;;;; files for more information.
15 (in-package "SB!IMPL")
17 (sb!int::/show0 "fdefinition.lisp 22")
19 ;;;; fdefinition (fdefn) objects
21 (defun make-fdefn (name)
24 (defun fdefn-name (fdefn)
25 (declare (type fdefn fdefn))
28 (defun fdefn-function (fdefn)
29 (declare (type fdefn fdefn)
30 (values (or function null)))
31 (fdefn-function fdefn))
33 (defun (setf fdefn-function) (fun fdefn)
34 (declare (type function fun)
37 (setf (fdefn-function fdefn) fun))
39 (defun fdefn-makunbound (fdefn)
40 (declare (type fdefn fdefn))
41 (fdefn-makunbound fdefn))
43 ;;; This function is called by !COLD-INIT after the globaldb has been
44 ;;; initialized, but before anything else. We need to install these
45 ;;; fdefn objects into the globaldb before any top level forms run, or
46 ;;; we will end up with two different fdefn objects being used for the
47 ;;; same function name. *!INITIAL-FDEFN-OBJECTS* is set up by GENESIS.
48 (defvar *!initial-fdefn-objects*)
49 (defun !fdefn-cold-init ()
50 (dolist (fdefn *!initial-fdefn-objects*)
51 (setf (info :function :definition (fdefn-name fdefn)) fdefn)))
53 (defun fdefinition-object (name create)
55 "Return the fdefn object for NAME. If it doesn't already exist and CREATE
56 is non-NIL, create a new (unbound) one."
57 (declare (values (or fdefn null)))
58 (unless (legal-function-name-p name)
59 (error 'simple-type-error
61 :expected-type '(or symbol list)
62 :format-control "invalid function name: ~S"
63 :format-arguments (list name)))
64 (let ((fdefn (info :function :definition name)))
65 (if (and (null fdefn) create)
66 (setf (info :function :definition name) (make-fdefn name))
69 ;;; FIXME: If the fundamental operation performed when
70 ;;; funcalling a symbol is %COERCE-NAME-TO-FUNCTION, which expands into
71 ;;; FDEFINITION-OBJECT, which does (INFO :FUNCTION :DEFINITION NAME),
72 ;;; that's a horrendously heavyweight way to implement SYMBOL-FUNCTION.
73 ;;; What compelling reason is there for all this hairiness? The only
74 ;;; thing I can think of is that it does give a place to store
75 ;;; SETF functions, but I don't think that's a good enough reason.
76 ;;; It might even be that the FDEFINITION arrangement saves a little
77 ;;; space, if the proportion of function-less symbols is high enough,
78 ;;; but I don't think that's a good enough reason, either.
79 ;;; I'd really like to wipe out FDEFN stuff root and branch, and
80 ;;; just store SETF functions in the symbol property list.
82 ;;; One problem with just doing the simple thing: What happens when
83 ;;; people call symbols which have no function definitions?
84 ;;; 1. Just hit "undefined function" error -- with no clue as to
85 ;;; what undefined function it was. (This might actually not be
86 ;;; too horrible, since the compiler warns you about undefined
87 ;;; functions and the debugger aims, with incomplete success,
88 ;;; to show you what form caused an error.)
89 ;;; 2. various solutions involving closures in the function slot,
90 ;;; all of which have the drawback of extra memory use and extra
91 ;;; difficulty in detecting when functions are undefined
92 ;;; 2a. Have every single symbol have an undefined function closure
93 ;;; which points back to it to tell you which undefined symbol it
94 ;;; was. (4 extra words per undefined symbol)
95 ;;; 2b. Play tricks with FDEFINITION, where the default SYMBOL-FUNCTION
96 ;;; for any function is an anonymous "undefined function" error
97 ;;; which doesn't tell you what the problem was, but if FDEFINITION
98 ;;; is ever called on an undefined symbol, it helpfully changes the
99 ;;; function definition to point to a closure which knows which
100 ;;; symbol caused the problem.
101 ;;; 4. Just don't sweat it except when DEBUG>SPEED, where the calling
102 ;;; convention gets tweaked to test for the undefined-function
103 ;;; function at call time and bail out with helpful information
105 ;;; 5. Require that the function calling convention be stereotyped
106 ;;; along the lines of
107 ;;; mov %ebx, local_immediate_3 ; Point to symbol.
108 ;;; mov %eax, symbol_function_offset(%eax) ; Point to function.
109 ;;; call *function_code_pointer(%eax) ; Go.
110 ;;; That way, it's guaranteed that on entry to a function, %EBX points
111 ;;; back to the symbol which was used to indirect into the function,
112 ;;; so the undefined function handler can base its complaint on that.
114 ;;; Another problem with doing the simple thing: people will want to
115 ;;; indirect through something in order to get to SETF functions, in
116 ;;; order to be able to redefine them. What will they indirect
117 ;;; through? This could be done with a hack, making an anonymous
118 ;;; symbol and linking it to the main symbol's SB!KERNEL:SETF-FUNCTION
119 ;;; property. The anonymous symbol could even point back to the symbol
120 ;;; it's the SETF function for, so that if the SETF function was
121 ;;; undefined at the time a call was made, the debugger could say
122 ;;; which function caused the problem. It'd probably be cleaner,
123 ;;; though, to use a new type of primitive object (SYMBOLOID?)
124 ;;; instead. It could probably be like symbol except that its name
125 ;;; could be any object and its value points back to the symbol which
126 ;;; owns it. Then the setf functions for FOO could be on the list (GET
127 ;;; FOO 'SB!KERNEL:SYMBOLOIDS)
129 ;;; FIXME: Oh, my. Now that I've started thinking about it, I
130 ;;; appreciate more fully how weird and twisted FDEFNs might be. Look
131 ;;; at the calling sequence for full calls. It goes and reads the
132 ;;; address of a function object from its own table of immediate
133 ;;; values, then jumps into that. Consider how weird that is. Not only
134 ;;; is it not doing indirection through a symbol (which I'd already
135 ;;; realized) but it's not doing indirection through
137 ;;; The compiler emits calls to this when someone tries to funcall a symbol.
138 (defun %coerce-name-to-function (name)
140 "Returns the definition for name, including any encapsulations. Settable
142 (let ((fdefn (fdefinition-object name nil)))
143 (or (and fdefn (fdefn-function fdefn))
144 (error 'undefined-function :name name))))
146 (defun %coerce-callable-to-function (callable)
147 (if (functionp callable)
149 (%coerce-name-to-function callable)))
151 ;;; This is just another name for %COERCE-NAME-TO-FUNCTION.
152 #!-sb-fluid (declaim (inline raw-definition))
153 (defun raw-definition (name)
154 ;; We know that we are calling %COERCE-NAME-TO-FUNCTION, so don't remind us.
155 (declare (optimize (inhibit-warnings 3)))
156 (%coerce-name-to-function name))
157 (defun (setf raw-definition) (function name)
158 (let ((fdefn (fdefinition-object name t)))
159 (setf (fdefn-function fdefn) function)))
161 ;;; FIXME: There seems to be no good reason to have both
162 ;;; %COERCE-NAME-TO-FUNCTION and RAW-DEFINITION names for the same
163 ;;; thing. And despite what the doc string of %COERCE-NAME-TO-FUNCTION
164 ;;; says, it's doesn't look settable. Perhaps we could collapse
165 ;;; %COERCE-TO-FUNCTION, RAW-DEFINITION, and (SETF RAW-DEFINITION)
166 ;;; into RAW-FDEFINITION and (SETF RAW-FDEFINITION), or
167 ;;; OUTER-FDEFINITION and (SETF OUTER-FDEFINITION).
169 ;;;; definition encapsulation
171 (defstruct (encapsulation-info (:constructor make-encapsulation-info
174 ;; This is definition's encapsulation type. The encapsulated
175 ;; definition is in the previous encapsulation-info element or
176 ;; installed as the global definition of some function name.
178 ;; the previous, encapsulated definition. This used to be installed
179 ;; as a global definition for some function name, but it was
180 ;; replaced by an encapsulation of type TYPE.
181 (definition nil :type function))
183 ;;; Replace the definition of NAME with a function that binds NAME's
184 ;;; arguments a variable named argument-list, binds name's definition
185 ;;; to a variable named basic-definition, and evaluates BODY in that
186 ;;; context. TYPE is whatever you would like to associate with this
187 ;;; encapsulation for identification in case you need multiple
188 ;;; encapsulations of the same name.
189 (defun encapsulate (name type body)
190 (let ((fdefn (fdefinition-object name nil)))
191 (unless (and fdefn (fdefn-function fdefn))
192 (error 'undefined-function :name name))
193 ;; We must bind and close over INFO. Consider the case where we
194 ;; encapsulate (the second) an encapsulated (the first)
195 ;; definition, and later someone unencapsulates the encapsulated
196 ;; (first) definition. We don't want our encapsulation (second) to
197 ;; bind basic-definition to the encapsulated (first) definition
198 ;; when it no longer exists. When unencapsulating, we make sure to
199 ;; clobber the appropriate INFO structure to allow
200 ;; basic-definition to be bound to the next definition instead of
201 ;; an encapsulation that no longer exists.
202 (let ((info (make-encapsulation-info type (fdefn-function fdefn))))
203 (setf (fdefn-function fdefn)
204 (lambda (&rest argument-list)
205 (declare (special argument-list))
206 (let ((basic-definition (encapsulation-info-definition info)))
207 (declare (special basic-definition))
210 ;;; This is like FIND-IF, except that we do it on a compiled closure's
212 (defun find-if-in-closure (test fun)
213 (dotimes (index (1- (get-closure-length fun)))
214 (let ((elt (%closure-index-ref fun index)))
215 (when (funcall test elt)
218 ;;; Find the encapsulation info that has been closed over.
219 (defun encapsulation-info (fun)
221 (= (get-type fun) sb!vm:closure-header-type)
222 (find-if-in-closure #'encapsulation-info-p fun)))
224 ;;; When removing an encapsulation, we must remember that
225 ;;; encapsulating definitions close over a reference to the
226 ;;; encapsulation-info that describes the encapsulating definition.
227 ;;; When you find an info with the target type, the previous info in
228 ;;; the chain has the ensulating definition of that type. We take the
229 ;;; encapsulated definition from the info with the target type, and we
230 ;;; store it in the previous info structure whose encapsulating
231 ;;; definition it describes looks to this previous info structure for
232 ;;; a definition to bind (see ENCAPSULATE). When removing the first
233 ;;; info structure, we do something conceptually equal, but
234 ;;; mechanically it is different.
235 (defun unencapsulate (name type)
237 "Removes NAME's most recent encapsulation of the specified TYPE."
238 (let* ((fdefn (fdefinition-object name nil))
239 (encap-info (encapsulation-info (fdefn-function fdefn))))
240 (declare (type (or encapsulation-info null) encap-info))
241 (cond ((not encap-info)
242 ;; It disappeared on us, so don't worry about it.
244 ((eq (encapsulation-info-type encap-info) type)
245 ;; It's the first one, so change the fdefn object.
246 (setf (fdefn-function fdefn)
247 (encapsulation-info-definition encap-info)))
249 ;; It must be an interior one, so find it.
251 (let ((next-info (encapsulation-info
252 (encapsulation-info-definition encap-info))))
254 ;; Not there, so don't worry about it.
256 (when (eq (encapsulation-info-type next-info) type)
257 ;; This is it, so unlink us.
258 (setf (encapsulation-info-definition encap-info)
259 (encapsulation-info-definition next-info))
261 (setf encap-info next-info))))))
264 (defun encapsulated-p (name type)
266 "Returns t if name has an encapsulation of the given type, otherwise nil."
267 (let ((fdefn (fdefinition-object name nil)))
268 (do ((encap-info (encapsulation-info (fdefn-function fdefn))
270 (encapsulation-info-definition encap-info))))
271 ((null encap-info) nil)
272 (declare (type (or encapsulation-info null) encap-info))
273 (when (eq (encapsulation-info-type encap-info) type)
278 ;;; KLUDGE: Er, it looks as though this means that
279 ;;; (FUNCALL (FDEFINITION 'FOO))
280 ;;; doesn't do the same thing as
282 ;;; That doesn't look like ANSI behavior to me. Look e.g. at the
283 ;;; ANSI definition of TRACE: "Whenever a traced function is invoked,
284 ;;; information about the call, ..". Try this:
285 ;;; (DEFUN FOO () (PRINT "foo"))
288 ;;; (FUNCALL (FDEFINITION 'FOO))
289 ;;; What to do? ANSI says TRACE "Might change the definitions of the functions
290 ;;; named by function-names." Might it be OK to just get punt all this
291 ;;; encapsulation stuff and go back to a simple but correct implementation of
292 ;;; TRACE? We'd lose the ability to redefine a TRACEd function and keep the
293 ;;; trace in place, but that seems tolerable to me. (Is the wrapper stuff
294 ;;; needed for anything else besides TRACE?)
296 ;;; The only problem I can see with not having a wrapper: If tracing
297 ;;; EQ, EQL, EQUAL, or EQUALP causes its function address to change,
298 ;;; it will mess up the MAKE-HASH-TABLE logic which uses EQ tests
299 ;;; on those function values. -- WHN 19990906
300 (defun fdefinition (name)
302 "Return name's global function definition taking care to respect any
303 encapsulations and to return the innermost encapsulated definition.
305 (let ((fun (raw-definition name)))
307 (let ((encap-info (encapsulation-info fun)))
309 (setf fun (encapsulation-info-definition encap-info))
312 (defvar *setf-fdefinition-hook* nil
314 "This holds functions that (SETF FDEFINITION) invokes before storing the
315 new value. These functions take the function name and the new value.")
317 (defun %set-fdefinition (name new-value)
319 "Set NAME's global function definition."
320 (declare (type function new-value) (optimize (safety 1)))
321 (let ((fdefn (fdefinition-object name t)))
322 ;; *SETF-FDEFINITION-HOOK* won't be bound when initially running top-level
323 ;; forms in the kernel core startup.
324 (when (boundp '*setf-fdefinition-hook*)
325 (dolist (f *setf-fdefinition-hook*)
326 (funcall f name new-value)))
328 (let ((encap-info (encapsulation-info (fdefn-function fdefn))))
333 (encapsulation-info-definition encap-info))))
335 (setf encap-info more-info)
337 (setf (encapsulation-info-definition encap-info)
340 (setf (fdefn-function fdefn) new-value))))))
342 ;;;; FBOUNDP and FMAKUNBOUND
344 (defun fboundp (name)
346 "Return true if name has a global function definition."
347 (let ((fdefn (fdefinition-object name nil)))
348 (and fdefn (fdefn-function fdefn) t)))
350 (defun fmakunbound (name)
352 "Make NAME have no global function definition."
353 (let ((fdefn (fdefinition-object name nil)))
355 (fdefn-makunbound fdefn)))