DRef Manual
Table of Contents
- 1 Links and Systems
- 2 Introduction
- 3 References
- 4 dtypes
- 5 Listing Definitions
- 6 Basic Operations
- 7 Basic Locative Types
- 8 Extending DRef
[in package DREF]
1 Links and Systems
Here is the official repository and the HTML documentation for the latest version.
DRef is bundled in the same repository with PAX, the documentation system.
- [system] "dref"
- Version: 0.4.4
- Description: Reify definitions, provide portable access to docstrings and source locations in an extensible framework.
- Long Description: defundefines a first-class object: afunction(01).defvardoes not. This library provides a way to refer to all definitions and smooths over the differences between implementations. This system has minimal dependencies. It autoloads thedref/fullasdf:system, which depends Alexandria and Swank.
- Licence: MIT, see COPYING.
- Author: Gábor Melis
- Mailto: mega@retes.hu
- Homepage: http://github.com/melisgl/mgl-pax/tree/master/dref
- Bug tracker: https://github.com/melisgl/mgl-pax/issues
- Source control: GIT
- Depends on: autoload, mgl-pax-bootstrap, named-readtables, pythonic-string-reader
- Defsystem depends on: mgl-pax.asdf
 
- [system] "dref/full"
- Description: - dref(- 0- 1) with everything loaded. There should be no need to explicitly load this system (or depend on it) as it is autoloaded as necessary by all publicly accessible functionality in- dref.- However, to get the dependencies, install this system. 
- Depends on: alexandria, dref, swank(?) 
- Defsystem depends on: mgl-pax.asdf 
 
2 Introduction
What if definitions were first-class objects?
Some defining forms do not create first-class
objects. For example, defun creates
function objects, but defvar does not create variable
objects as no such thing exists. The main purpose of this library is
to fill this gap with the introduction of dref objects:
(defvar *my-var* nil
  "This is my var.")
(dref '*my-var* 'variable)
==> #<DREF *MY-VAR* VARIABLE>drefs just package up a name (*my-var*) and a
locative (variable) then check that the definition
actually exists:
(dref 'junk 'variable)
.. debugger invoked on LOCATE-ERROR:
..   Could not locate JUNK VARIABLE.The Basic Operations on definitions in DRef are arglist, docstring
and source-location.
(docstring (dref '*my-var* 'variable))
=> "This is my var."For definitions associated with objects, the definition can be
located from the object:
(locate #'print)
==> #<DREF PRINT FUNCTION>These objects designate their definitions, so (docstring #'print)
works. Extending DRef and these operations is possible through
Defining Locative Types. It is also possible to define
new operations. For example, PAX makes
pax:document extensible through pax:document-object*.
Finally, existing definitions can be queried with definitions and
dref-apropos:
(definitions 'dref-ext:arglist*)
==> (#<DREF ARGLIST* GENERIC-FUNCTION>
-->  #<DREF ARGLIST* (METHOD (MGL-PAX::GO-DREF))>
-->  #<DREF ARGLIST* (METHOD (LAMBDA-DREF))>
-->  #<DREF ARGLIST* (METHOD (TYPE-DREF))>
-->  #<DREF ARGLIST* (METHOD (METHOD-DREF))>
-->  #<DREF ARGLIST* (METHOD (FUNCTION-DREF))>
-->  #<DREF ARGLIST* (METHOD (COMPILER-MACRO-DREF))>
-->  #<DREF ARGLIST* (METHOD (MACRO-DREF))>
-->  #<DREF ARGLIST* (METHOD (SETF-DREF))> #<DREF ARGLIST* (METHOD (T))>
-->  #<DREF ARGLIST* (METHOD (DREF))>
-->  #<DREF ARGLIST* (UNKNOWN
-->                   (DECLAIM ARGLIST*
-->                            FTYPE))>)(dref-apropos 'locate-error :package :dref)
==> (#<DREF LOCATE-ERROR CONDITION> #<DREF LOCATE-ERROR FUNCTION>)
(dref-apropos "ate-err" :package :dref :external-only t)
==> (#<DREF LOCATE-ERROR CONDITION> #<DREF LOCATE-ERROR FUNCTION>)
3 References
After the Introduction, here we get into the details. Of special interest are:
- The - xreffunction to construct an arbitrary reference without any checking of validity.
- locateand- drefto look up the definition of an object (e.g- #'print) or a reference (e.g.- (xref 'print 'function)).
- resolveto find the first-class (non-- xref) object the definition refers to, if any.
The Basic Operations (arglist, docstring, source-location) know how to
deal with references (discussed in the Extending DRef).
- 
An xref(cross-reference) is a reference. It may represent some kind of definition of its name in the context given by its locative. The definition may not exist and the locative may even be invalid. The subclassdrefrepresents definitions that exist.
- [function] xref name locative - A shorthand for - (make-instance 'xref :name name :locative locative)to create- xrefobjects. It does no error checking: the- locative-typeof- locative-typeneed not be defined, and the- locative-argsneed not be valid. Use- locateor the- dreffunction to create- drefobjects.
- [function] xref= xref1 xref2 - See if - xref1and- xref2have the same- xref-nameand- xref-locativeunder- equal. Comparing like this makes most sense for- drefs. However, two- xrefs different under- xref=may denote the same- drefs.
- 
drefs can be thought of as definitions that actually exist, although changes in the system can invalidate them (for example, adrefto a function definition can be invalidated byfmakunbound).drefs must be created withlocateor thedreffunction.Two drefs created in the same dynamic environment denote the same thing if and only if they arexref=.
- [function] locate object &optional (errorp t) - Return a - drefrepresenting the definition of- object.- objectmust be a supported first-class object, a- dref, or an- xref:- (locate #'print) ==> #<DREF PRINT FUNCTION>- (locate (locate #'print)) ==> #<DREF PRINT FUNCTION>- (locate (xref 'print 'function)) ==> #<DREF PRINT FUNCTION>- When - objectis a- dref, it is simply returned.- Else, a - locate-error(- 0- 1) is signalled if- objectis an- xrefwith an invalid locative, or if no corresponding definition is found. If- errorpis- nil, then- nilis returned instead.- (locate (xref 'no-such-function 'function)) .. debugger invoked on LOCATE-ERROR: .. Could not locate NO-SUCH-FUNCTION FUNCTION. .. NO-SUCH-FUNCTION does not name a function.- (locate (xref 'print '(function xxx))) .. debugger invoked on LOCATE-ERROR: .. Could not locate PRINT #'XXX. .. Bad arguments (XXX) for locative FUNCTION with lambda list NIL.- (locate "xxx") .. debugger invoked on LOCATE-ERROR: .. Could not locate "xxx".- Use the - xreffunction to construct an- xrefwithout error checking.- See Extending - locate.
- [function] dref name locative &optional (errorp t) - Shorthand for - (locate (xref name locative) errorp).
- [function] resolve object &optional (errorp t) - If - objectis an- xref, then return the first-class object associated with its definition if any. Return- objectif it's not an- xref. Thus, the value returned is never an- xref. The second return value is whether resolving succeeded.- (resolve (dref 'print 'function)) ==> #<FUNCTION PRINT> => T- (resolve #'print) ==> #<FUNCTION PRINT> => T- If - objectis an- xref, and the definition for it cannot be- located, then- locate-error(- 0- 1) is signalled.- (resolve (xref 'undefined 'variable)) .. debugger invoked on LOCATE-ERROR: .. Could not locate UNDEFINED VARIABLE.- If there is a definition, but there is no first-class object corresponding to it, then - resolve-error(- 0- 1) is signalled or- nilis returned depending on- errorp:- (resolve (dref '*print-length* 'variable)) .. debugger invoked on RESOLVE-ERROR: .. Could not resolve *PRINT-LENGTH* VARIABLE.- (resolve (dref '*print-length* 'variable) nil) => NIL => NIL- resolveis a partial inverse of- locate: if a- drefis- resolveable, then- locateing the object it resolves to recovers the- drefequivalent to the original (- xref=and of the same type but not- eq).- Can be extended via - resolve*.
- [condition] locate-error error - Signalled by - locatewhen the definition cannot be found, and- errorpis true.
- [condition] resolve-error error - Signalled by - resolvewhen the object defined cannot be returned, and- errorpis true.
3.1 Dissecting References
- [reader] xref-locative xref (:locative) - The locative of the reference. - The locative is normalized by replacing single-element lists with their only element: - (xref 'print 'function) ==> #<XREF PRINT FUNCTION>- (xref 'print '(function)) ==> #<XREF PRINT FUNCTION>
- 
The same as xref-locative, but only works ondrefs. Use it as a statement of intent.
- 
The object from which locateconstructed thisdref.dref-originmay have presentation arguments, which are not included inlocative-argsas is the case with theinitformargument of thevariablelocative:(dref '*standard-output* '(variable "see-below")) ==> #<DREF *STANDARD-OUTPUT* VARIABLE>(dref-origin (dref '*standard-output* '(variable "see-below"))) ==> #<XREF *STANDARD-OUTPUT* (VARIABLE "see-below")>The initformargument overrides the global binding of*standard-output*when it'spax:documented:(first-line (pax:document (dref '*standard-output* '(variable "see-below")) :stream nil)) => "- [variable] *STANDARD-OUTPUT* \"see-below\""
- [function] locative-type locative - Return locative type of the locative - locative. This is the first element of- locativeif it's a list. If it's a symbol, it's that symbol itself.
- [function] locative-args locative - Return the - restof locative- locativeif it's a list. If it's a symbol, then return- nil. See locative.
The following convenience functions are compositions of
{locative-type, locative-args} and {xref-locative,
dref-locative}.
3.2 References Glossary
- 
A reference is a name plus a locative, and it identifies a possible definition. References are of class xref. When a reference is adref, it may also be called a definition.
- 
A definition is a reference that identifies a concrete definition. Definitions are of class dref. A definitionresolves to the first-class object associated with the definition if such a thing exists, andlocateon this object returns the canonicaldrefobject that's unique underxref=.The kind of a definition is given by its locative type. There is at most one definition for any given name and locative type. Equivalently, there can be no two definitions of the same dref-nameanddref-locative-typebut differentdref-locative-args.
- 
Names are symbols, strings and nested lists of the previous, which name functions, types, packages, etc. Together with locatives, they form references. 
- 
Locatives specify a type of definition such as functionorvariable. Together with names, they form references.In their compound form, locatives may have arguments (see locative-args) as in(method (number)). In fact, their atomic form is shorthand for the common no-argument case: that is,functionis equivalent to(function).A locative is valid if it names an existing locative type and its locative-argsmatch that type's lambda-list (seedefine-locative-type).(arglist (dref 'method 'locative)) => (&REST QUALIFIERS-AND-SPECIALIZERS) => :DESTRUCTURINGSee xref-locativeanddref-locative.
- 
The locative type is the part of a locative that identifies what kind definition is being referred to. This is always a symbol. Locative types are defined with define-locative-typeordefine-pseudo-locative-type. See Basic Locative Types for the list locative types built into DRef, and PAX Locatives for those in PAX.Also, see locative-type,xref-locative-type,dref-locative-type, Defining Locative Types.
- 
references may have arguments (see Defining Locative Types) that do not affect the behaviour of locateand the Basic Operations, but which may be used for other, "presentation" purposes. For example, thevariablelocative'sinitformargument is used for presentation bypax:document. Presentation arguments are available viadref:dref-originbut do not feature indref-locativeto ensure the uniqueness of the definition underxref=.
4 dtypes
dtypes are to Lisp types what locative types are to classes.
A dtype is either
- a locative type such as - function,- typeand- clhs, or
- a full locative such as - (method (number))and- (clhs section), or
- nil(the empty- dtype) and- t(that encompasses all- lisp-locative-types), or
- named with - define-dtype(such as- pseudoand- top), or
- a - satisfiesform with the name of a function that takes a single definition as its argument.
dtypes are used in definitions and dref-apropos to filter the set of
definitions as in
(definitions 'print :dtype '(not unknown))
==> (#<DREF PRINT (CLHS FUNCTION)> #<DREF PRINT FUNCTION>)(dref-apropos "type specifier" :dtype 'pseudo)
==> (#<DREF "1.4.4.6" #1=(CLHS SECTION)> #<DREF "1.4.4.6.1" #1#>
-->  #<DREF "1.4.4.6.2" #1#> #<DREF "1.4.4.6.3" #1#>
-->  #<DREF "1.4.4.6.4" #1#> #<DREF "4.2.3" #1#>
-->  #<DREF "atomic type specifier" #2=(CLHS GLOSSARY-TERM)>
-->  #<DREF "compound type specifier" #2#>
-->  #<DREF "derived type specifier" #2#> #<DREF "type specifier" #2#>)- [macro] define-dtype name lambda-list &body body - Like - deftype, but it may expand into other- dtypes.- The following example defines - method*as the locative- methodwithout its direct locative subtypes.- (define-dtype method* () '(and method (not reader) (not writer)))
- 
This is the top of the dtypehierarchy, much liketfor Lisp types. It expands to (ortpseudo). Whiletmatches every normal Lisp object and objectless definitions present in the running Lisp (seelisp-locative-types),topmatches even pseudo definitions (seepseudo-locative-types).
- 
This is the union of all pseudo-locative-types. It expands to(or ,@(pseudo-locative-types)).
- [function] dtypep dref dtype - See if - drefis of- dtype.- Atomic locatives: If - dtypeis a locative type, then it matches definitions with that locative type and its locative subtypes.- Because - constantis defined with- variableamong its- locative-supertypes:- (dtypep (dref 'pi 'constant) 'variable) => T- (dtypep (dref 'number 'class) 'type) => T- It is an error if - dtypeis an- atom(- 0- 1) but is not a locative type, but (the empty) argument list of bare locative types are not checked even if having no arguments makes them invalid locatives.
- Compound locatives: Locatives in their compound form are validated and must match exactly (under - equal, as in- xref=).- (defparameter *d* (dref 'dref* '(method (t t t)))) (defparameter *d2* (dref 'dref* '(method :around (t t t)))) (dtypep *d* 'method) => T (dtypep *d* '(accessor)) .. debugger invoked on SIMPLE-ERROR: .. Bad arguments NIL for locative ACCESSOR with lambda list (CLASS-NAME). (dtypep *d* '(method (t t t))) => T (dtypep *d2* '(method (t t t))) => NIL
- dtypemay be constructed with- and,- orand- notfrom Lisp types, locative types, full locatives and named- dtypes:- (dtypep (dref 'locate-error 'condition) '(or condition class)) => T (dtypep (dref nil 'type) '(and type (not class))) => T
- For - (member &rest objs), each of- objs is- located and- drefis matched against them with- xref=:- (dtypep (locate #'print) `(member ,#'print)) => T
- For - (satisfies pred), the predicate- predis funcalled with- dref.
- dtypemay be named by- define-dtype:- (dtypep (locate #'car) 'top) => T
 
5 Listing Definitions
- [function] definitions name &key (dtype t) - List all definitions of - namethat are of- dtypeas- drefs.- Just as - (dref name locative)returns the canonical definition, the- dref-names of returned by- definitionsmay be different from- name:- (definitions "PAX") ==> (#<DREF "MGL-PAX" PACKAGE>)- (definitions 'mgl-pax) ==> (#<DREF "mgl-pax" ASDF/SYSTEM:SYSTEM> #<DREF "MGL-PAX" PACKAGE>)- Similarly, - dref-locative-typemay be more made more specific:- (definitions 'dref:locate-error :dtype 'type) ==> (#<DREF LOCATE-ERROR CONDITION>)- Can be extended via - map-definitions-of-name.
- [function] dref-apropos name &key package external-only case-sensitive (dtype t) - Return a list of - drefs corresponding to existing definitions that match the various arguments. First,- (dref-apropos nil)lists all definitions in the running Lisp and maybe more (e.g.- mgl-pax:clhs). Arguments specify how the list of definitions is filtered.- dref-apropositself is similar to- cl:apropos-list, but- it finds definitions not - symbols,
- it supports an extensible definition types, and 
- filtering based on them. 
 - PAX has a live browsing frontend. - Roughly speaking, when - nameor- packageis a- symbol, they must match the whole name of the definition:- (dref-apropos 'method :package :dref :external-only t) ==> (#<DREF METHOD CLASS> #<DREF METHOD LOCATIVE>)- On the other hand, when - nameor- packageis a- string(- 0- 1), they are matched as substrings to the definition's name- princ-to-stringed:- (dref-apropos "method" :package :dref :external-only t) ==> (#<DREF SETF-METHOD LOCATIVE> #<DREF METHOD CLASS> --> #<DREF METHOD LOCATIVE> #<DREF METHOD-COMBINATION CLASS> --> #<DREF METHOD-COMBINATION LOCATIVE>)- Definitions that are not of - dtype(see- dtypep) are filtered out:- (dref-apropos "method" :package :dref :external-only t :dtype 'class) ==> (#<DREF METHOD CLASS> #<DREF METHOD-COMBINATION CLASS>)- When - packageis- :none, only non-symbol names are matched:- (dref-apropos "dref" :package :none) ==> (#<DREF "DREF" PACKAGE> #<DREF "DREF-EXT" PACKAGE> --> #<DREF "DREF-TEST" PACKAGE> #<DREF "dref" ASDF/SYSTEM:SYSTEM> --> #<DREF "dref/full" ASDF/SYSTEM:SYSTEM> --> #<DREF "dref/test" ASDF/SYSTEM:SYSTEM> --> #<DREF "dref/test-autoload" ASDF/SYSTEM:SYSTEM>)- The exact rules of filtering are as follows. Let - cbe the name of the candidate definition from the list of all definitions that we are matching against the arguments and denote its string representation- (princ-to-string c)with- p. Note that- princ-to-stringdoes not print the package of symbols. We say that two strings match if- case-sensitiveis- niland they are- equalp, or- case-sensitiveis true and they are- equal.- case-sensitiveaffects substring comparisons too.- If - nameis a- symbol, then its- symbol-namemust match- p.
- If - nameis a- string, then it must be a substring of- p.
- If - packageis- :any, then- cmust be a- symbol.
- If - packageis- :none, then- cmust not be a- symbol.
- If - packageis not- nil,- :anyor- :none, then- cmust be a symbol.
- If - packageis a- package, it must be- eqto the- symbol-packageof- c.
- If - packageis a- symbolother than- nil,- :anyand- :none, then its- symbol-namemust match the- package-nameor one of the- package-nicknamesof- symbol-packageof- c.
- If - packageis a- string, then it must be a substring of the- package-nameof- symbol-packageof- c.
- If - external-onlyand- cis a symbol, then- cmust be external in a matching package.
- dtypematches candidate definition- dif- (dtypep d dtype).
 - Can be extended via MAP-REFERENCES-OF-TYPE and - map-definitions-of-name.
- [glossary-term] reverse definition order - Lists of locative types and aliases are sometimes in reverse order of the time of their definition. This order is not affected by redefinition, regardless of whether it's by - define-locative-type,- define-pseudo-locative-type,- define-symbol-locative-typeor- define-locative-alias.
- 
Return a list of non-alias locative types. This is the unionoflisp-locative-typesandpseudo-locative-types, which is the set of constituents of thedtypetop.This list is in reverse definition order. 
- [function] lisp-locative-types - Return the locative types that correspond to Lisp definitions, which typically have - source-location. These are defined with- define-locative-typeand- define-symbol-locative-typeand are the constituents of- dtype- t.- This list is in reverse definition order. 
- [function] pseudo-locative-types - Return the locative types that correspond to non-Lisp definitions. These are the ones defined with - define-pseudo-locative-typeand are the constituents of- dtype- pseudo.- This list is in reverse definition order. 
- 
Return the list of locatives aliases, defined with define-locative-alias.This list is in reverse definition order. 
6 Basic Operations
The following functions take a single argument, which may be a
dref, or an object denoting its own definition (see
locate).
- [function] arglist object - Return the arglist of the definition of - objector- nilif the arglist cannot be determined.- The second return value indicates whether the arglist has been found. As the second return value, - :ordinaryindicates an ordinary lambda list,- :macroa macro lambda list,- :deftypea deftype lambda list, and- :destructuringa destructuring lambda list. Other non-- nilvalues are also allowed.- (arglist #'arglist) => (OBJECT) => :ORDINARY- (arglist (dref 'define-locative-type 'macro)) => (LOCATIVE-TYPE-AND-LAMBDA-LIST LOCATIVE-SUPERTYPES &OPTIONAL DOCSTRING DREF-DEFCLASS-FORM) => :MACRO- (arglist (dref 'method 'locative)) => (&REST QUALIFIERS-AND-SPECIALIZERS) => :DESTRUCTURING- This function supports - macros,- compiler-macros,- setffunctions,- functions,- generic-functions,- methods,- types,- locatives. Note that- arglistdepends on the quality of- swank-backend:arglist. With the exception of SBCL, which has perfect support, all Lisp implementations have minor omissions:- deftypelambda lists on ABCL, AllegroCL, CLISP, CCL, CMUCL, ECL;
- default values in - macrolambda lists on AllegroCL;
- various edge cases involving traced functions. 
 - Can be extended via - arglist*
- [function] docstring object - Return the docstring from the definition of - object. As the second value, return the- *package*that was in effect when the docstring was installed or- nilif it cannot be determined (this is used by- pax:documentwhen Parsing the docstring). This function is similar in purpose to- cl:documentation.- Note that some locative types such as - asdf:systems and- declarations have no docstrings, and some Lisp implementations do not record all docstrings. The following are known to be missing:- compiler-macrodocstrings on ABCL, AllegroCL, CCL, ECL;
- method-combinationdocstrings on ABCL, AllegroCL.
 - Can be extended via - docstring*.
- [function] source-location object &key error - Return the Swank source location for the defining form of - object.- The returned Swank location object is to be accessed only through the Source Locations API or to be passed to e.g Slime's - slime-goto-source-location.- If no source location was found, - if - erroris- nil, then return- nil;
- if - erroris- :error, then return a list of the form- (:error <error-message>)suitable for- slime-goto-source-location;
- if - erroris- t, then signal an- errorcondition with the same error message as in the previous case.
 - Note that the availability of source location information varies greatly across Lisp implementations. - Can be extended via - source-location*.
7 Basic Locative Types
The following are the locative types supported out of the
box. As all locative types, they are named by symbols. When there is
a CL type corresponding to the reference's locative type, the
references can be resolved to a unique object as is the case in
(resolve (dref 'print 'function))
==> #<FUNCTION PRINT>
=> TEven if there is no such CL type, the arglist, the docstring, and
the source-location of the defining form is usually recorded unless
otherwise noted.
The basic locative types and their inheritance structure is loosely
based on the doc-type argument of cl:documentation.
7.1 Locatives for Variables
- [locative] variable &optional initform - Direct locative subtypes: glossary-term, section, constant
 - Refers to a global special variable. - initform, or if not specified, the global value of the variable is to be used for presentation.- (dref '*print-length* 'variable) ==> #<DREF *PRINT-LENGTH* VARIABLE>- variablereferences do not- resolve.
- [locative] constant &optional initform - Direct locative supertypes: variable
 - Refers to a constant variable defined with - defconstant.- initform, or if not specified, the value of the constant is included in the documentation. The- constantlocative is like the- variablelocative, but it also checks that its object is- constantp.- constantreferences do not- resolve.
7.2 Locatives for Macros
- 
- Direct locative subtypes: setf-method, setf-function
 Refers to a setf expander (see defsetfanddefine-setf-expander).Setf functions (e.g. (defun (setf name) ...)or the same withdefgeneric) are handled by thesetf-function,setf-generic-function, andsetf-methodlocatives.setfexpander references do notresolve.
- 
Refers to a global macro, typically defined with defmacro, or to a special operator.macroreferences resolve to themacro-functionof theirnameor signalresolve-error(01) if that'snil.
- 
Refers to a global symbol macro, defined with define-symbol-macro. Note that sincedefine-symbol-macrodoes not support docstrings, PAX defines methods on thedocumentationgeneric function specialized on(doc-type (eql 'symbol-macro)).(define-symbol-macro my-mac 42) (setf (documentation 'my-mac 'symbol-macro) "This is MY-MAC.") (documentation 'my-mac 'symbol-macro) => "This is MY-MAC."symbol-macroreferences do notresolve.
- 
- Direct locative subtypes: setf-compiler-macro
 Refers to a compiler-macro-function, typically defined withdefine-compiler-macro.
- [locative] setf-compiler-macro - Direct locative supertypes: compiler-macro
 - Refers to a compiler macro with a setf function name. - setf-compiler-macroreferences do not- resolve.
7.3 Locatives for Functions and Methods
- 
- Direct locative subtypes: structure-accessor, setf-function, generic-function
 Refers to a global function, typically defined with defun. The name must be a function name. It is also allowed to referencegeneric-functions asfunctions:(dref 'docstring 'function) ==> #<DREF DOCSTRING FUNCTION>
- 
- Direct locative subtypes: structure-accessor, setf-generic-function 
 Refers to a global function(01) with a setf function name.(defun (setf ooh) ()) (locate #'(setf ooh)) ==> #<DREF OOH SETF-FUNCTION> (dref 'ooh 'setf-function) ==> #<DREF OOH SETF-FUNCTION> (dref '(setf ooh) 'function) ==> #<DREF OOH SETF-FUNCTION>
- 
- Direct locative supertypes: function 
- Direct locative subtypes: setf-generic-function 
 Refers to a generic-function, typically defined withdefgeneric. The name must be a function name.
- [locative] setf-generic-function - Direct locative supertypes: generic-function, setf-function
 - Refers to a global - generic-functionwith a setf function name.- (defgeneric (setf oog) ()) (locate #'(setf oog)) ==> #<DREF OOG SETF-GENERIC-FUNCTION> (dref 'oog 'setf-function) ==> #<DREF OOG SETF-GENERIC-FUNCTION> (dref '(setf oog) 'function) ==> #<DREF OOG SETF-GENERIC-FUNCTION>
- [locative] method &rest qualifiers-and-specializers - Direct locative subtypes: writer, reader, setf-method
 - Refers to a - method. name must be a function name.- method-qualifiers-and-specializershas the form- (<QUALIFIER>* <SPECIALIZERS>)- For example, the method - (defgeneric foo-gf (x y z) (:method :around (x (y (eql 'xxx)) (z string)) (values x y z)))- can be referred to as - (dref 'foo-gf '(method :around (t (eql xxx) string))) ==> #<DREF FOO-GF (METHOD :AROUND (T (EQL XXX) STRING))>- methodis not- exportable-locative-type-p.
- [locative] setf-method &rest method-qualifiers-and-specializers - Refers to a - methodof a- setf-generic-function.- (defgeneric (setf oog) (v) (:method ((v string)))) (locate (find-method #'(setf oog) () (list (find-class 'string)))) ==> #<DREF OOG (SETF-METHOD (STRING))> (dref 'oog '(setf-method (string))) ==> #<DREF OOG (SETF-METHOD (STRING))> (dref '(setf oog) '(method (string))) ==> #<DREF OOG (SETF-METHOD (STRING))>
- 
Refers to a method-combination, defined withdefine-method-combination.method-combinationreferences do notresolve.
- [locative] reader class-name - Refers to a - :readermethod in a- defclass:- (defclass foo () ((xxx :reader foo-xxx))) (dref 'foo-xxx '(reader foo)) ==> #<DREF FOO-XXX (READER FOO)>
- [locative] writer class-name - Like - accessor, but refers to a- :writermethod in a- defclass.
- [locative] accessor class-name - Direct locative supertypes: reader, writer, setf-method
 - Refers to an - :accessorin a- defclass.- An - :accessorin- defclasscreates a reader and a writer method. Somewhat arbitrarily,- accessorreferences- resolveto the writer method but can be- located with either.
- [locative] structure-accessor &optional structure-class-name - Direct locative supertypes: setf-function, function
 - Refers to an accessor function generated by - defstruct. A- locate-errorcondition is signalled if the wrong- structure-class-nameis provided.- Note that there is no portable way to detect structure accessors, and on some platforms, - (locate #'my-accessor),- definitionsand- dref-aproposwill return- function(- 0- 1) references instead. On such platforms,- structure-accessorreferences do not- resolve.
7.4 Locatives for Types and Declarations
- 
- Direct locative subtypes: class
 This locative can refer to types and classes and conditions, simply put, to things defined by deftype,defclassanddefine-condition.(deftype my-type () t) (dref 'my-type 'type) ==> #<DREF MY-TYPE TYPE>(dref 'xref 'type) ==> #<DREF XREF CLASS>(dref 'locate-error 'type) ==> #<DREF LOCATE-ERROR CONDITION>typereferences do notresolve.
- 
- Direct locative supertypes: class
 Refers to a structure-class, typically defined withdefstruct.
- 
Refers to a declaration, used in declare,declaimandproclaim.User code may also define new declarations with CLTL2 functionality, but there is currently no way to provide a docstring, and their arglistis alwaysnil.(cl-environments:define-declaration my-decl (&rest things) (values :declare (cons 'foo things)))declarationreferences do notresolve.Also, source-locationon declarations currently only works on SBCL.
7.5 Locatives for the Condition System
- 
- Direct locative supertypes: class
 Although conditionis notsubtypepofclass, actual condition objects are commonly instances of a condition class that is a CLOS class. HyperSpec ISSUE:CLOS-CONDITIONS and ISSUE:CLOS-CONDITIONS-AGAIN provide the relevant history.Whenever a classdenotes acondition, itsdref-locative-typewill becondition:(dref 'locate-error 'class) ==> #<DREF LOCATE-ERROR CONDITION>
- 
A locative to refer to the definition of a restart defined by define-restart.
- [macro] define-restart symbol lambda-list &body docstring - Associate a definition with the name of a restart, which must be a symbol. - lambda-listshould be what calls like- (invoke-restart '<symbol> ...)must conform to, but this not enforced.- PAX "defines" standard CL restarts such as - use-value(- 0- 1) with- define-restart:- (first-line (source-location-snippet (source-location (dref 'use-value 'restart)))) => "(define-restart use-value (value)"- Note that while there is a - cl:restartclass, its instances have no docstring or source location.
7.6 Locatives for Packages and Readtables
- 
Refers to an already loaded asdf:system(those inasdf:registered-systems). The name may be anythingasdf:find-systemsupports.asdf:systemis notexportable-locative-type-p.
- 
Refers to a package, defined bydefpackageormake-package. The name may be anythingfind-packagesupports.packageis notexportable-locative-type-p.
- 
Refers to a named readtabledefined withnamed-readtables:defreadtable, which associates a global name and a docstring with the readtable object. The name may be anythingfind-readtablesupports.readtablereferencesresolvetofind-readtableon their name.
7.7 Locatives for Unknown Definitions
- [locative] unknown dspec - This locative type allows PAX to work in a limited way with definition types it doesn't know. - unknowndefinitions come from- definitions, which uses- swank/backend:find-definitions. The following examples show PAX stuffing the Swank dspec- (:define-alien-type double-float)into an- unknownlocative on SBCL.- (definitions 'double-float) ==> (#<DREF DOUBLE-FLOAT CLASS> --> #<DREF DOUBLE-FLOAT (UNKNOWN (:DEFINE-ALIEN-TYPE DOUBLE-FLOAT))>)- (dref 'double-float '(unknown (:define-alien-type double-float))) ==> #<DREF DOUBLE-FLOAT (UNKNOWN (:DEFINE-ALIEN-TYPE DOUBLE-FLOAT))>- arglistand- docstringreturn- nilfor- unknowns, but- source-locationworks.
7.8 Locatives for DRef Constructs
- 
- Direct locative subtypes: locative
 Locative for dtypes defined withdefine-dtypeandlocativetypes.dtypeis tolocativeastypeis toclass.The topof thedtypehierarchy:(dref 'top 'dtype) ==> #<DREF TOP DTYPE>This very definition: (dref 'dtype 'locative) ==> #<DREF DTYPE LOCATIVE>
- 
- Direct locative supertypes: dtype
 This is the locative for locative types defined with define-locative-type,define-pseudo-locative-typeanddefine-locative-alias.(first-line (source-location-snippet (source-location (dref 'macro 'locative)))) => "(define-locative-type macro ()"
- [locative] lambda &key arglist arglist-type docstring docstring-package file file-position snippet &allow-other-keys - A pseudo locative type that carries its - arglist,- docstringand- source-locationin the locative itself. See- make-source-locationfor the description of- file,- file-position, and- snippet.- lambdareferences do not- resolve. The name must be- nil.- (arglist (dref nil '(lambda :arglist ((x y) z) :arglist-type :macro))) => ((X Y) Z) => :MACRO- (docstring (dref nil '(lambda :docstring "xxx" :docstring-package :dref))) => "xxx" ==> #<PACKAGE "DREF">- (source-location-file (source-location (dref nil '(lambda :file "xxx.el")))) => "xxx.el"- Also, see the - pax:includelocative.
8 Extending DRef
8.1 Extension Tutorial
Let's see how to tell DRef about new kinds of definitions through
the example of the implementation of the class locative. Note that
this is a verbatim pax:include of the sources. Please
ignore any internal machinery. The first step is to define the
locative type:
(define-locative-type class (type)
  "Naturally, CLASS is the locative type for [CLASS][class]es.
  Also, see the related CONDITION locative.")
Then, we make it possible to look up class definitions:
(define-locator class ((class class))
  (make-instance 'class-dref :name (class-name class) :locative 'class))
(define-lookup class (symbol locative-args)
  (unless (and (symbolp symbol)
               (find-class symbol nil))
    (locate-error "~S does not name a class." symbol))
  (make-instance 'class-dref :name symbol :locative 'class))
define-locator makes (locate (find-class 'dref)) work, while
define-lookup is for (dref 'dref 'class). Naturally, for locative
types that do not define first-class objects, the first method
cannot be defined.
Finally, we define a resolve* method to recover the class
object from a class-dref. We also specialize docstring* and
source-location*:
(defmethod resolve* ((dref class-dref))
  (find-class (dref-name dref)))
(defmethod docstring* ((class class))
  (documentation* class t))
(defmethod source-location* ((dref class-dref))
  (swank-source-location* (resolve dref) (dref-name dref) 'class))
We took advantage of having just made the class locative type being
resolveable, by specializing docstring* on the class class.
source-location* was specialized on class-dref to demonstrate how
this can be done for non-resolveable locative types.
Classes have no arglist, so no arglist* method is needed. In the
following, we describe the pieces in detail.
8.2 Locative Type Hierarchy
Locative types form their own hierarchy, that
is only superficially similar to the Lisp class hierarchy.
The hierarchies of lisp-locative-types and pseudo-locative-types
are distinct. That is, the dref-class of a Lisp locative type must
not be a subclass of a pseudo one, and vice versa. This is enforced
by define-locative-type and define-pseudo-locative-type.
- [function] dref-class locative-type - Return the name of the - classused to represent definitions with- locative-type. This is always a subclass of- dref. Returns- nilif- locative-typeis not a valid locative type.- Note that the actual - type-ofa- drefis mostly intended for Extending DRef. Hence, it is hidden when a- drefis printed:- (dref 'print 'function) ==> #<DREF PRINT FUNCTION> (type-of *) => FUNCTION-DREF- Due to Canonicalization, the actual type may be a proper subtype of - dref-class:- (dref 'documentation 'function) ==> #<DREF DOCUMENTATION GENERIC-FUNCTION> (type-of *) => GENERIC-FUNCTION-DREF (subtypep 'generic-function-dref 'function-dref) => T => T
- [function] locative-type-direct-supers locative-type - List the locative types whose - dref-classes are direct superclasses of the- dref-classof- locative-type. These can be considered supertypes of- locative-typein the sense of- dtypep.- This is ordered as in the corresponding definition. 
- [function] locative-type-direct-subs locative-type - List the locative types whose - dref-classes are direct subclasses of the- dref-classof- locative-type. These can be considered subtypes of- locative-typein the sense of- dtypep.- This list is in reverse definition order. 
8.3 Defining Locative Types
- [macro] define-locative-type locative-type-and-lambda-list locative-supertypes &optional docstring dref-defclass-form - Declare - locative-typeas a- locative, which is the first step in Extending DRef.- Simple example - To define a locative type called - dummythat takes no arguments and is not a locative subtype of any other locative type:- (define-locative-type dummy () "Dummy docstring.")- With this definition, only the locatives - dummyand its equivalent form- (dummy)are valid. The above defines a- dref(- 0- 1) subclass called- dummy-drefin the current package. All definitions with locative type- dummyand its locatives subtypes must be instances of- dummy-dref.- (locate 'dummy 'locative)refers to this definition. That is,- arglist,- docstringand- source-locationall work on it.
- Complex example - dummymay have arguments- xand- yand inherit from locative types- l1and- l2:- (define-locative-type (dummy x &key y) (l1 l2) "Dummy docstring." (defclass dummy-dref () ((xxx :initform nil :accessor dummy-xxx))))- One may change name of - dummy-dref, specify superclasses and add slots as with- defclass. Behind the scenes, the- drefclasses of- l1and- l2are added automatically to the list of superclasses.
 - Arguments: - The general form of - locative-type-and-lambda-listis (- locative-type- &rest- lambda-list), where- locative-typeis a- symbol, and- lambda-listis a destructuring lambda list. The- locative-argsof- drefs with locative type- locative-type(the argument given to this macro) always conform to this lambda list. See- check-locative-args.- If - locative-type-and-lambda-listis a single symbol, then that's interpreted as- locative-type, and- lambda-listis- nil.
- locative-supertypesis a list of locative types whose- dref-classes are added to prepended to the list of superclasses this definition.
 - Locative types defined with - define-locative-typecan be listed with- lisp-locative-types.
- [macro] define-pseudo-locative-type locative-type-and-lambda-list locative-supertypes &optional docstring dref-defclass-form - Like - define-locative-type, but declare that- locative-typedoes not correspond to definitions in the running Lisp. Definitions with pseudo locatives are of- dtype- pseudoand are not listed by default by- definitions.- Locative types defined with - define-pseudo-locative-typecan be listed with- pseudo-locative-types.
- [macro] define-locative-alias alias locative-type &body docstring - Define - aliasthat can be substituted for- locative-type(both- symbols) for the purposes of- locateing.- locative-typemust exist (i.e. be among- locative-types). For example, let's define- objectas an alias of the- classlocative:- (define-locative-alias object class)- Then, - locateing with- objectwill find the- class:- (dref 'xref 'object) ==> #<DREF XREF CLASS>- The - locative-argsof- object(none in the above) are passed on to- class.- (arglist (dref 'object 'locative)) => (&REST ARGS) => :DESTRUCTURING- Note that - locative-aliasesare not- locative-typesand are not valid- dtypes.- Also, see Locative Aliases in PAX. 
8.3.1 Symbol Locatives
Let's see how the opaque define-symbol-locative-type and the
obscure define-definer-for-symbol-locative-type macros work together
to simplify the common task of associating definition with a symbol
in a certain context.
- [macro] define-symbol-locative-type locative-type-and-lambda-list locative-supertypes &optional docstring dref-class-def - Similar to - define-locative-type, but it assumes that all things- locateable with- locative-typeare going to be symbols defined with a definer defined with- define-definer-for-symbol-locative-type. Symbol locatives are for attaching a definition (along with arglist, documentation and source location) to a symbol in a particular context. An example will make everything clear:- (define-symbol-locative-type direction () "A direction is a symbol.") (define-definer-for-symbol-locative-type define-direction direction "With DEFINE-DIRECTION, one can document what a symbol means when interpreted as a DIRECTION.") (define-direction up () "UP is equivalent to a coordinate delta of (0, -1).")- After all this, - (dref 'up 'direction)refers to the- define-directionform above.- The - dref-classof the defined locative type inherits from- symbol-locative-dref, which may be used for specializing when implementing new operations.
- [macro] define-definer-for-symbol-locative-type name locative-type &body docstring - Define a macro with - namethat can be used to attach a lambda list, documentation, and source location to a symbol in the context of- locative-type. The defined macro's arglist is- (symbol lambda-list &optional docstring).- locative-typeis assumed to have been defined with- define-symbol-locative-type.
8.4 Extending locate
Internally, locate finds an initial dref of its object
argument with a lookup or with a
locator. This initial dref is then canonicalized
with a series of casts. In more detail, the process
is as follows.
- If the objectargument oflocateis adref, then it is returned without processing.
Else, locate first needs to finds the initial definition.
8.4.1 Initial Definition
locate can find the initial definition in one of two ways:
- With direct lookup - If - objectis an- xref(- 0- 1), then the lookup for (- xref-locative-type- object) is invoked. For an- xrefwith the locative- (method (number)), this would be the lookup defined as- (define-lookup method (name locative-args) ...)
- With locator search - Else, - objectis a normal Lisp object, such as a- methodobject from- find-method. The first of- lisp-locative-typeswhose locator succeeds provides the initial definition, which may be defined like this:- (define-locator method ((obj method)) ...)- This is a locator that returns definitions with the - methodlocative type and takes an argument named- objof class- method(which is like a specializer in- defmethod).- lisp-locative-typesare tried one by one in the order specified there.
- For a given locative type, if there are multiple locators, standard CLOS method selection applies. 
 
8.4.2 Canonicalization
The initial definition thus found is then canonicalized so that
there is a unique definition under xref=:
(locate #'arglist*)
==> #<DREF ARGLIST* GENERIC-FUNCTION>
(dref 'arglist* 'function)
==> #<DREF ARGLIST* GENERIC-FUNCTION>
(dref 'arglist* 'generic-function)
==> #<DREF ARGLIST* GENERIC-FUNCTION>Canonicalization is performed by recursively attempting to
downcast the current definition to one of its
locative-type-direct-subs in a depth-first manner, backtracking if a
cast fails.
Default Downcast
Downcasting to direct locative subtypes is performed by default by looking up the definition where the locative type is replaced with its sub while the name and the locative args remain the same.
Cast Name Change
Casts must be careful about changing dref-name.
Their dref argument and the dref returned must have the
same dref-name (under equal, see xref=) or it must be possible to
upcast the returned value to the dref argument's dref-locative-type.
- Implementation note - The purpose of this rule is to allow - dtypepanswer this correctly:- (defclass foo () ((a :accessor foo-a))) (dref '(setf foo-a) '(method (t foo))) ==> #<DREF FOO-A (ACCESSOR FOO)> (dtypep * '(method (t foo))) => T ;; Internally, DTYPEP upcast #<DREF FOO-A (ACCESSOR FOO)> ;; and checks that the locative args of the resulting ;; definition match those in (METHOD (T FOO)). (locate* ** 'method) ==> #<DREF (SETF FOO-A) (METHOD (T FOO))>- For even more background, also note that if the name remains the same but locative args change, then - dtypepcan simply check with- drefif there is a definition of the name with the given locative:- (defclass foo () ((r :reader foo-r))) (dref 'foo-r '(reader foo)) ==> #<DREF FOO-R (READER FOO)> (dtypep * '(method (foo))) => T ;; Behind the scenes, DTYPEP does this: (xref= ** (dref 'foo-r '(method (foo)))) => T
8.4.3 Defining Lookups, Locators and Casts
As we have seen, the Initial Definition is provided either by a lookup or a locator, then Canonicalization works with casts. Here, we look at how to define these.
Implementation note: All three are currently implemented as
methods of generic functions with eql specializers for
the locative type, which may easily prove to be problematic down the
road. To make future changes easier, the generic function and the
methods are hidden behind e.g. the define-lookup and call-lookup
macros.
- 
Enable runtime verification of invariants during locatecalls. This carries a performance penalty and is intended for testing and debugging.In particular, enforce the rule of Cast Name Change and that lookups, locators and casts obey the following: - The value returned must be either - nilor a- dref(- 0- 1). Alternatively,- locate-error(- 0- 1) may be signalled.
- If a - drefis returned, then its- dref-locative-typemust be- locative-type, and its class must be the- dref-classof- locative-type.
- locative-argsmust be congruent with the destructuring lambda list in the definition of- locative-type.
 
- [macro] define-lookup locative-type (name locative-args) &body body - Define a method of looking up definitions of - locative-typewith the given- locative-args. Lookups are invoked by- locatewhen its- objectargument is an- xref(- 0- 1) with- locative-typebut it is not a- dref(- 0- 1), as in the case of- (dref 'print 'function). When called, the variables- nameand- locative-argsare bound to- xref-nameand- xref-locative-argsof the- xref.- locative-argsis validated with- check-locative-argsbefore- bodyis evaluated.- (define-lookup variable (name locative-args) (unless (special-variable-name-p name) (locate-error)) (make-instance 'variable-dref :name name :locative 'variable))- locative-typeis a valid locative type.
- nameand- locative-argsare both- symbols.
 - The above are enforced at macro-expansion time. - bodymust follow the rules in- *check-locate*.
 
- [macro] call-lookup name locative-type locative-args - Call the lookup for - locative-typewith- nameand- locative-args.
- [macro] define-locator locative-type ((object class)) &body body - Define a method of finding the definition with - locative-typeof instances of- class. When a locator's- bodyis evaluated,- objectis bound to such an instance.- (define-locator class ((class class)) (make-instance 'class-dref :name (class-name class) :locative 'class))- locative-typeis one of- lisp-locative-types. This is because- pseudo-locative-typesnever- resolveto first-class objects.
- objectis a- symbol.
- classnames a- classthat is not a subtype of- xref. For how to convert definitions from one locative type to another, see- define-cast.
 - The above are enforced at macro-expansion time. - bodymust follow the rules in- *check-locate*.
 - In contrast to when the Initial Definition is created from an - xref(see- define-lookup), here- locative-argsare determined from- object.
- [macro] call-locator object locative-type - Call the locator for - locative-typewith- object.
- [macro] define-cast locative-type ((dref dref-class)) &body body - Define a method of converting a definition to another with - locative-type. When a cast's- bodyis evaluated,- drefis bound to an instance- dref-class, which denotes a valid but potentially non-canonical definition.- Note the Default Downcast often suffices, and defining a cast is only necessary if the name or the locative args change: - (define-cast accessor ((dref reader-dref)) (let ((name (dref-name dref)) (class (second (dref-locative dref)))) (when (ignore-errors (find-accessor-slot-definition name class)) (make-instance 'accessor-dref :name name :locative `(accessor ,class)))))- locative-typeis a valid locative type.
- If - locative-typeis one of- pseudo-locative-types, then- dref-classmust be of another pseudo locative type.
- dref-classis either a direct downcast or an potentially non-direct upcast.- Downcast: In this case, - locative-typeis one of- locative-type-direct-subsof (- dref-class-to-locative-type- dref-class).- Downcasting to non-direct subtypes is done in multiple steps. Consequently,the - bodyof a downcast can rely on (- class-of- dref) being- class, not any subclass thereof.
- Upcast: - locative-typeis different but reachable from (- dref-class-to-locative-type- dref-class) by repeatedly choosing one of- locative-type-direct-supers. Upcasting to non-direct supertypes is done in one step.
 
 - The above are enforced at macro-expansion time. - bodymust follow the rules in- *check-locate*, including those in Cast Name Change.
 
- [function] locate-error &optional format-control &rest format-args - Call this function to signal a - locate-errorcondition from the dynamic extent of a- locatecall, that is, from the- bodys of- define-lookup,- define-locatorand- define-cast. It is an error to call- locate-errorelsewhere.- format-control, if non-- nil, is a format control for which- format-argsare suitable.
- [macro] check-locative-args locative-type locative-args - Signal a - locate-errorcondition if- locative-argsdo not match the- lambda-listargument of- locative-type(not evaluated).
8.5 Extending Everything Else
- [generic-function] resolve* dref - Return the object defined by the definition - drefrefers to. Signal a- resolve-errorcondition by calling the- resolve-errorfunction if the lookup fails.- To keep - resolvea partial inverse of- locate,- define-locatormay be necessary for- resolveable definitions. This function is for extending- resolve. Do not call it directly.- It is an error for methods of this generic function to return an - xref.
- [function] resolve-error &rest format-and-args - Call this function to signal a - resolve-errorcondition from the dynamic extent of a- resolve*method. It is an error to call- resolve-errorelsewhere.- format-and-args, if non-- nil, is a format string and arguments suitable for- format.
- [generic-function] map-definitions-of-name fn name locative-type - Call - fnwith- drefs which can be- located with an- xref(- 0- 1) with- name,- locative-typeand some- locative-args. The strange wording here is because there may be multiple ways (and thus- xrefs) that refer to the same definition.- For most locative types, there is at most one such definition, but for - method, for example, there may be many. The default method simply does- (dref name locative-type nil)and calls- fnwith result if- drefsucceeds.- fnmust not be called with the same (under- xref=) definition multiple times.- This function is for extending - definitionsand- dref-apropos. Do not call it directly.
- [generic-function] map-definitions-of-type fn locative-type - Call - fnwith- drefs which can be- located with an- xref(- 0- 1) with- locative-typewith some- nameand- locative-args.- The default method forms - xrefs by combining each interned symbol as names with- locative-typeand no- locative-argsand calls- fnif it- locates a definition.- fnmay be called with- drefs that are- xref=but differ in the- xrefin their- dref-origin.- This function is for extending - dref-apropos. Do not call it directly.
- [generic-function] arglist* object - To extend - arglist, specialize- objecton a normal Lisp type or on a subclass of- dref.- arglistfirst calls- arglist*with its- objectargument. If that doesn't work (i.e. the second value returned is- nil), then it calls- arglist*with- objecteither- resolved (if it's a- dref) or- located (if it's not a- dref).- The default method returns - nil,- nil.
- There is also a method specialized on - drefs, that looks up the- definition-propertycalled- arglistand returns its value with- values-list. Thus, an arglist and its kind can be specified with something like- (setf (definition-property xref 'arglist) (list arglist :destructuring))
 - This function is for extension only. Do not call it directly. 
- [generic-function] docstring* object - To extend - docstring, specialize- objecton a normal Lisp type or on a subclass of- dref.- docstringfirst calls- docstring*with its- objectargument. If that doesn't work (i.e.- nilis returned), then it calls- docstring*with- objecteither- resolved (if it's a- dref) or- located (if it's not a- dref).- The default method returns - nil.
- There is also a method specialized on - drefs, that looks up the- definition-propertycalled- docstringand returns its value with- values-list. Thus, a docstring and a package can be specified with something like- (setf (definition-property xref 'docstring) (list docstring *package*))
 - This function is for extension only. Do not call it directly. 
- [generic-function] source-location* object - To extend - source-location, specialize- objecton a normal Lisp type or on a subclass of- dref.- source-locationfirst calls- source-location*with its- objectargument. If that doesn't work (i.e.- nilor- (:error <message>)is returned), then it calls- source-location*with- objecteither- resolved (if it's a- dref) or- located (if it's not a- dref).- source-locationreturns the last of the- (:error <message>)s encountered or a generic error message if only- nils were returned.- The default method returns - nil.
- There is also a method specialized on - drefs, that looks up the- definition-propertycalled- source-location. If present, it must be a function of no arguments that returns a source location or- nil. Typically, this is set up in the defining macro like this:- (setf (definition-property xref 'source-location) (this-source-location))
 - This function is for extension only. Do not call it directly. 
8.5.1 Definition Properties
Arbitrary data may be associated with definitions.
This mechanism is used by arglist*, docstring* and
source-location* for easy extension.
The following functions take an xref argument and not a dref(0 1) to
allow working with non-canonical or
non-existent definitions.
- [function] definition-property xref indicator - Return the value of the property associated with - xrefwhose name is- eql(- 0- 1) to- indicator. The second return value indicates whether the property was found.- setfable.
- [function] delete-definition-property xref indicator - Delete the property associated with - xrefwhose name is- eql(- 0- 1) to- indicator. Return true if the property was found.
- [function] definition-properties xref - Return the properties of - xrefas an association list.
- [function] delete-definition-properties xref - Delete all properties associated with - xref.
- [function] move-definition-properties from-xref to-xref - Associate all properties of - from-xrefwith- to-xref, as if readding them one-by-one with- (setf definition-property), and deleting them from- from-xrefwith- delete-definition-property.
8.6 dref-classes
These are the dref-classes corresponding to Basic Locative Types.
They are exported to make it possible to go beyond the
Basic Operations (e.g. pax:document-object*). For
Defining Locative Types, they are not necessary, as
define-locative-type handles inheritance automatically based on its
locative-supertypes argument.
- [class] symbol-locative-dref dref - All locative types defined with - define-symbol-locative-typeinherit from this class.
8.7 Source Locations
These represent the file or buffer position of a defining
form and are returned by the source-location function. For
the details, see the Elisp function slime-goto-source-location.
- [function] make-source-location &key file file-position buffer buffer-position snippet - Make a Swank source location. The ultimate reference is - slime.el. When- snippetis provided, the match nearest to- file-positionis determined (see the Elisp- slime-isearchand- source-location-adjusted-file-position).
- [function] source-location-p object - See if - objectis a source location object.
- [function] source-location-file location - Return the name of the file of the defining form. This may be - nil, for example, if- locationis of a defining form that was entered at the REPL, or compiled in the- *slime-scratch*buffer.
- [function] source-location-file-position location - Return the file position of the defining form or - nilif it's not available. The first position is 0.
- [function] source-location-buffer location - Return the name of the Emacs buffer of the defining form or - nilif there is no such Emacs buffer.
- [function] source-location-buffer-position location - Return the position of the defining form in - source-location-bufferor- nilif it's not available. The first position is 1.
- [function] source-location-snippet location - Return the defining form or a prefix of it as a string or - nilif it's not available.
- [function] source-location-adjusted-file-position location - Return the actual file position - locationpoints to allowing for some deviation from the raw- source-location-file-position, which is adjusted by searching for the nearest occurrence of- source-location-snippetin the file. Needless to say, this can be a very expensive operation.- If - source-location-fileis- nil,- nilis returned. If there is no snippet, or it doesn't match, then- source-location-file-position(or 0 if that's- nil) is returned.- This is a non-interactive companion to the Elisp function - slime-location-offset, supporting only file positions and non-partial matching of snippets.
- 
The value of this macro form is a function of no arguments that returns its own source-location.