DRef Manual
Table of Contents
- 1 Links and Systems
- 2 Introduction
- 3 References
- 4
dtype
s - 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.0
- Description: Reify definitions, provide portable access to docstrings and source locations in an extensible framework.
- Long Description:
defun
defines a first-class object: afunction
(0
1
).defvar
does 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/full
asdf: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/dref
- Bug tracker: https://github.com/melisgl/mgl-pax/issues
- Source control: GIT
- Depends on: 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 indref
.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>
dref
s 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
locate
d 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:locate*)
==> (#<DREF LOCATE* GENERIC-FUNCTION>
--> #<DREF LOCATE* (METHOD NIL (GLOSSARY-TERM))>
--> #<DREF LOCATE* (METHOD NIL (SECTION))>
--> #<DREF LOCATE* (METHOD NIL (READTABLE))>
--> #<DREF LOCATE* (METHOD NIL (PACKAGE))>
--> #<DREF LOCATE* (METHOD NIL (ASDF/SYSTEM:SYSTEM))>
--> #<DREF LOCATE* (METHOD NIL (CLASS))>
--> #<DREF LOCATE* (METHOD NIL (METHOD))>
--> #<DREF LOCATE* (METHOD NIL (GENERIC-FUNCTION))>
--> #<DREF LOCATE* (METHOD NIL (FUNCTION))>
--> #<DREF LOCATE* (METHOD (:AROUND) (T))>
--> #<DREF LOCATE* (METHOD NIL (T))> #<DREF LOCATE* (METHOD NIL (XREF))>
--> #<DREF LOCATE* (METHOD NIL (DREF))>)
(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
xref
function to construct an arbitrary reference without any checking of validity.locate
anddref
to look up the definition of an object (e.g#'print
) or a reference (e.g.(xref 'print 'function)
).resolve
to 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 subclassdref
represents definitions that exist.
[function] xref name locative
A shorthand for
(make-instance 'xref :name name :locative locative)
to createxref
objects. It does no error checking: thelocative-type
oflocative-type
need not be defined, and thelocative-args
need not be valid. Uselocate
or thedref
function to createdref
objects.
[function] xref= xref1 xref2
See if
xref1
andxref2
have the samexref-name
andxref-locative
underequal
. Comparing like this makes most sense fordref
s. However, twoxref
s different underxref=
may denote the samedref
s.
-
dref
s can be thought of as definitions that actually exist, although changes in the system can invalidate them (for example, adref
to a function definition can be invalidated byfmakunbound
).dref
s must be created withlocate
or thedref
function.Two
dref
s created in the same dynamic environment denote the same thing if and only if they arexref=
.
[function] locate object &optional (errorp t)
Return a
dref
representing the definition ofobject
.object
must be a supported first-class object, adref
, or anxref
:(locate #'print) ==> #<DREF PRINT FUNCTION>
(locate (locate #'print)) ==> #<DREF PRINT FUNCTION>
(locate (xref 'print 'function)) ==> #<DREF PRINT FUNCTION>
When
object
is adref
, it is simply returned.Else, a
locate-error
(0
1
) is signalled ifobject
is anxref
with an invalid locative, or if no corresponding definition is found. Iferrorp
isnil
, thennil
is 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
xref
function to construct anxref
without 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
object
is anxref
, then return the first-class object associated with its definition if any. Returnobject
if it's not anxref
. Thus, the value returned is never anxref
. The second return value is whether resolving succeeded.(resolve (dref 'print 'function)) ==> #<FUNCTION PRINT> => T
(resolve #'print) ==> #<FUNCTION PRINT> => T
If
object
is anxref
, and the definition for it cannot belocate
d, thenlocate-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 ornil
is returned depending onerrorp
:(resolve (dref '*print-length* 'variable)) .. debugger invoked on RESOLVE-ERROR: .. Could not resolve *PRINT-LENGTH* VARIABLE.
(resolve (dref '*print-length* 'variable) nil) => NIL => NIL
resolve
is a partial inverse oflocate
: if adref
isresolve
able, thenlocate
ing the object it resolves to recovers thedref
equivalent to the original (xref=
and of the same type but noteq
).Can be extended via
resolve*
.
[condition] locate-error error
Signalled by
locate
when the definition cannot be found, anderrorp
is true.
[condition] resolve-error error
Signalled by
resolve
when the object defined cannot be returned, anderrorp
is 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 ondref
s. Use it as a statement of intent.
-
The object from which
locate
constructed thisdref
.dref-origin
may have presentation arguments, which are not included inlocative-args
as is the case with theinitform
argument of thevariable
locative:(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
initform
argument overrides the global binding of*standard-output*
when it'spax:document
ed:(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 oflocative
if it's a list. If it's a symbol, it's that symbol itself.
[function] locative-args locative
Return the
rest
of locativelocative
if it's a list. If it's a symbol, then returnnil
. 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 definitionresolve
s to the first-class object associated with the definition if such a thing exists, andlocate
on this object returns the canonicaldref
object 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-name
anddref-locative-type
but differentdref-locative-args
.
-
Names are symbols, lists or strings which name functions, types, packages, etc. Together with locatives, they form references.
-
Locatives specify a type of definition such as
function
orvariable
. 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,function
is equivalent to(function)
.A locative is valid if it names an existing locative type and its
locative-args
match that type's lambda-list (seedefine-locative-type
).(arglist (dref 'method 'locative)) => (METHOD-QUALIFIERS METHOD-SPECIALIZERS) => :DESTRUCTURING
See
xref-locative
anddref-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-type
ordefine-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
locate
and the Basic Operations, but which may be used for other, "presentation" purposes. For example, thevariable
locative'sinitform
argument is used for presentation bypax:document
. Presentation arguments are available viadref:dref-origin
but do not feature indref-locative
to ensure the uniqueness of the definition underxref=
.
4 dtype
s
dtype
s are to Lisp types what locative types are to class
es.
A dtype
is either
a locative type such as
function
,type
andclhs
, ora full locative such as
(method () (number))
and(clhs section)
, ornil
(the emptydtype
) andt
(that encompasses alllisp-locative-types
), ornamed with
define-dtype
(such aspseudo
andtop
), ora
satisfies
form with the name of a function that takes a single definition as its argument.
dtype
s 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 otherdtype
s.The following example defines
method*
as the locativemethod
without its direct locative subtypes.(define-dtype method* () '(and method (not reader) (not writer)))
-
This is the top of the
dtype
hierarchy, much liket
for Lisp types. It expands to (or
t
pseudo
). Whilet
matches every normal Lisp object and objectless definitions present in the running Lisp (seelisp-locative-types
),top
matches 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
dref
is ofdtype
.Atomic locatives: If
dtype
is a locative type, then it matches definitions with that locative type and its locative subtypes.Because
constant
is defined withvariable
among itslocative-supertypes
:(dtypep (dref 'pi 'constant) 'variable) => T
(dtypep (dref 'number 'class) 'type) => T
It is an error if
dtype
is anatom
(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 inxref=
).(defparameter *d* (dref 'dref* '(method () (t t t)))) (defparameter *d2* (dref 'dref* '(method (:around) (t t t)))) (dtypep *d* 'method) => T (dtypep *d* '(method)) .. debugger invoked on SIMPLE-ERROR: .. Bad arguments NIL for locative METHOD with lambda list .. (METHOD-QUALIFIERS METHOD-SPECIALIZERS). (dtypep *d* '(method () (t t t))) => T (dtypep *d2* '(method () (t t t))) => NIL
dtype
may be constructed withand
,or
andnot
from Lisp types, locative types, full locatives and nameddtype
s:(dtypep (dref 'locate-error 'condition) '(or condition class)) => T (dtypep (dref nil 'type) '(and type (not class))) => T
For
(member &rest objs)
, each ofobj
s islocate
d anddref
is matched against them withxref=
:(dtypep (locate #'print) `(member ,#'print)) => T
For
(satisfies pred)
, the predicatepred
is funcalled withdref
.dtype
may be named bydefine-dtype
:(dtypep (locate #'car) 'top) => T
5 Listing Definitions
[function] definitions name &key (dtype t)
List all definitions of
name
that are ofdtype
asdref
s.Just as
(dref name locative)
returns the canonical definition, thedref-name
s of returned bydefinitions
may be different fromname
:(definitions "PAX") ==> (#<DREF "MGL-PAX" PACKAGE>)
(definitions 'mgl-pax) ==> (#<DREF "mgl-pax" ASDF/SYSTEM:SYSTEM> #<DREF "MGL-PAX" PACKAGE>)
Similarly,
dref-locative-type
may 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
dref
s 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-apropos
itself is similar tocl:apropos-list
, butit finds definitions not
symbol
s,it supports an extensible definition types, and
filtering based on them.
PAX has a live browsing frontend.
Roughly speaking, when
name
orpackage
is asymbol
, 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
name
orpackage
is astring
(0
1
), they are matched as substrings to the definition's nameprinc-to-string
ed:(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
(seedtypep
) are filtered out:(dref-apropos "method" :package :dref :external-only t :dtype 'class) ==> (#<DREF METHOD CLASS> #<DREF METHOD-COMBINATION CLASS>)
When
package
is: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
c
be 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)
withp
. Note thatprinc-to-string
does not print the package of symbols. We say that two strings match ifcase-sensitive
isnil
and they areequalp
, orcase-sensitive
is true and they areequal
.case-sensitive
affects substring comparisons too.If
name
is asymbol
, then itssymbol-name
must matchp
.If
name
is astring
, then it must be a substring ofp
.If
package
is:any
, thenc
must be asymbol
.If
package
is:none
, thenc
must not be asymbol
.If
package
is notnil
,:any
or:none
, thenc
must be a symbol.If
package
is apackage
, it must beeq
to thesymbol-package
ofc
.If
package
is asymbol
other thannil
,:any
and:none
, then itssymbol-name
must match thepackage-name
or one of thepackage-nicknames
ofsymbol-package
ofc
.If
package
is astring
, then it must be a substring of thepackage-name
ofsymbol-package
ofc
.If
external-only
andc
is a symbol, thenc
must be external in a matching package.dtype
matches candidate definitiond
if(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-type
ordefine-locative-alias
.
-
Return a list of non-alias locative types. This is the
union
oflisp-locative-types
andpseudo-locative-types
, which is the set of constituents of thedtype
top
.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 withdefine-locative-type
anddefine-symbol-locative-type
and are the constituents ofdtype
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-type
and are the constituents ofdtype
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
object
ornil
if the arglist cannot be determined.The second return value indicates whether the arglist has been found. As the second return value,
:ordinary
indicates an ordinary lambda list,:macro
a macro lambda list,:deftype
a deftype lambda list, and:destructuring
a destructuring lambda list. Other non-nil
values 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)) => (METHOD-QUALIFIERS METHOD-SPECIALIZERS) => :DESTRUCTURING
This function supports
macro
s,compiler-macro
s,setf
functions,function
s,generic-function
s,method
s,type
s,locative
s. Note thatarglist
depends on the quality ofswank-backend:arglist
. With the exception of SBCL, which has perfect support, all Lisp implementations have minor omissions:deftype
lambda lists on ABCL, AllegroCL, CLISP, CCL, CMUCL, ECL;default values in
macro
lambda 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 ornil
if it cannot be determined (this is used bypax:document
when Parsing the docstring). This function is similar in purpose tocl:documentation
.Note that some locative types such as
asdf:system
s anddeclaration
s have no docstrings, and some Lisp implementations do not record all docstrings. The following are known to be missing:compiler-macro
docstrings on ABCL, AllegroCL, CCL, ECL;method-combination
docstrings 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
error
isnil
, then returnnil
;if
error
is:error
, then return a list of the form(:error <error-message>)
suitable forslime-goto-source-location
;if
error
ist
, then signal anerror
condition 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 resolve
d to a unique object as is the case in
(resolve (dref 'print 'function))
==> #<FUNCTION PRINT>
=> T
Even 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>
variable
references do notresolve
.
- [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. Theconstant
locative is like thevariable
locative, but it also checks that its object isconstantp
.constant
references do notresolve
.
7.2 Locatives for Macros
- [locative] setf
- Direct locative subtypes: setf-method, setf-function
Refers to a setf expander (see
defsetf
anddefine-setf-expander
).Setf functions (e.g.
(defun (setf name) ...)
or the same withdefgeneric
) are handled by thesetf-function
,setf-generic-function
, andsetf-method
locatives.setf
expander references do notresolve
.
-
Refers to a global macro, typically defined with
defmacro
, or to a special operator.macro
references resolve to themacro-function
of theirname
or signalresolve-error
(0
1
) if that'snil
.
-
Refers to a global symbol macro, defined with
define-symbol-macro
. Note that sincedefine-symbol-macro
does not support docstrings, PAX defines methods on thedocumentation
generic 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-macro
references do notresolve
.
- [locative] compiler-macro
- 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-macro
references do notresolve
.
7.3 Locatives for Functions and Methods
- [locative] function
- 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-function
s asfunction
s:(dref 'docstring 'function) ==> #<DREF DOCSTRING FUNCTION>
- [locative] setf-function
Direct locative subtypes: structure-accessor, setf-generic-function
Refers to a global
function
(0
1
) 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>
- [locative] generic-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-function
with 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 method-qualifiers method-specializers
- Direct locative subtypes: writer, reader, setf-method
Refers to a
method
. name must be a function name.method-qualifiers
andmethod-specializers
are similar to thecl:find-method
's arguments of the same names. 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))>
method
is notexportable-locative-type-p
.
- [locative] setf-method method-qualifiers method-specializers
Refers to a
method
of asetf-generic-function
.(defgeneric (setf oog) () (:method ())) (locate (find-method #'(setf oog) () ())) ==> #<DREF OOG (SETF-METHOD NIL NIL)> (dref 'oog '(setf-method () ())) ==> #<DREF OOG (SETF-METHOD NIL NIL)> (dref '(setf oog) '(method () ())) ==> #<DREF OOG (SETF-METHOD NIL NIL)>
-
Refers to a
method-combination
, defined withdefine-method-combination
.method-combination
references do notresolve
.
- [locative] reader class-name
Refers to a
:reader
method in adefclass
:(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:writer
method in adefclass
.
- [locative] accessor class-name
- Direct locative supertypes: reader, writer, setf-method
Refers to an
:accessor
in adefclass
.An
:accessor
indefclass
creates a reader and a writer method. Somewhat arbitrarily,accessor
referencesresolve
to the writer method but can belocate
d with either.
- [locative] structure-accessor &optional structure-class-name
- Direct locative supertypes: setf-function, function
Refers to an accessor function generated by
defstruct
. Alocate-error
condition is signalled if the wrongstructure-class-name
is provided.Note that there is no portable way to detect structure accessors, and on some platforms,
(locate #'my-accessor)
,definitions
anddref-apropos
will returnfunction
(0
1
) references instead. On such platforms,structure-accessor
references do notresolve
.
7.4 Locatives for Types and Declarations
- [locative] type
- Direct locative subtypes: class
This locative can refer to types and classes and conditions, simply put, to things defined by
deftype
,defclass
anddefine-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>
type
references do notresolve
.
- [locative] class
Naturally,
class
is the locative type forclass
es.Also, see the related
condition
locative.
- [locative] structure
- Direct locative supertypes: class
Refers to a
structure-class
, typically defined withdefstruct
.
-
Refers to a declaration, used in
declare
,declaim
andproclaim
.User code may also define new declarations with CLTL2 functionality, but there is currently no way to provide a docstring, and their
arglist
is alwaysnil
.(cl-environments:define-declaration my-decl (&rest things) (values :declare (cons 'foo things)))
declaration
references do notresolve
.Also,
source-location
on declarations currently only works on SBCL.
7.5 Locatives for the Condition System
- [locative] condition
- Direct locative supertypes: class
Although
condition
is notsubtypep
ofclass
, 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
class
denotes acondition
, itsdref-locative-type
will 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-list
should 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
) withdefine-restart
:(first-line (source-location-snippet (source-location (dref 'use-value 'restart)))) => "(define-restart use-value (value)"
Note that while there is a
cl:restart
class, 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-system
supports.asdf:system
is notexportable-locative-type-p
.
-
Refers to a
package
, defined bydefpackage
ormake-package
. The name may be anythingfind-package
supports.package
is notexportable-locative-type-p
.
-
Refers to a named
readtable
defined withnamed-readtables:defreadtable
, which associates a global name and a docstring with the readtable object. The name may be anythingfind-readtable
supports.readtable
referencesresolve
tofind-readtable
on 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.
unknown
definitions come fromdefinitions
, which usesswank/backend:find-definitions
. The following examples show PAX stuffing the Swank dspec(:define-alien-type double-float)
into anunknown
locative 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))>
arglist
anddocstring
returnnil
forunknown
s, butsource-location
works.
7.8 Locatives for DRef Constructs
- [locative] dtype
- Direct locative subtypes: locative
Locative for
dtype
s defined withdefine-dtype
andlocative
types.dtype
is tolocative
astype
is toclass
.The
top
of thedtype
hierarchy:(dref 'top 'dtype) ==> #<DREF TOP DTYPE>
This very definition:
(dref 'dtype 'locative) ==> #<DREF DTYPE LOCATIVE>
- [locative] locative
- Direct locative supertypes: dtype
This is the locative for locative types defined with
define-locative-type
,define-pseudo-locative-type
anddefine-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
,docstring
andsource-location
in the locative itself. Seemake-source-location
for the description offile
,file-position
, andsnippet
.lambda
references do notresolve
. The name must benil
.(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:include
locative.
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
resolve
able, by specializing docstring*
on the class
class.
source-location*
was specialized on class-dref
to demonstrate how
this can be done for non-resolve
able 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
class
used to represent definitions withlocative-type
. This is always a subclass ofdref
. Returnsnil
iflocative-type
is not a valid locative type.Note that the actual
type-of
adref
is mostly intended for Extending DRef. Hence, it is hidden when adref
is 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-class
es are direct superclasses of thedref-class
oflocative-type
. These can be considered supertypes oflocative-type
in the sense ofdtypep
.This is ordered as in the corresponding definition.
[function] locative-type-direct-subs locative-type
List the locative types whose
dref-class
es are direct subclasses of thedref-class
oflocative-type
. These can be considered subtypes oflocative-type
in the sense ofdtypep
.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-type
as alocative
, which is the first step in Extending DRef.Simple example
To define a locative type called
dummy
that 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
dummy
and its equivalent form(dummy)
are valid. The above defines adref
(0
1
) subclass calleddummy-dref
in the current package. All definitions with locative typedummy
and its locatives subtypes must be instances ofdummy-dref
.(locate 'dummy 'locative)
refers to this definition. That is,arglist
,docstring
andsource-location
all work on it.Complex example
dummy
may have argumentsx
andy
and inherit from locative typesl1
andl2
:(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 withdefclass
. Behind the scenes, thedref
classes ofl1
andl2
are added automatically to the list of superclasses.
Arguments:
The general form of
locative-type-and-lambda-list
is (locative-type
&rest
lambda-list
), wherelocative-type
is asymbol
, andlambda-list
is a destructuring lambda list. Thelocative-args
ofdref
s with locative typelocative-type
(the argument given to this macro) always conform to this lambda list. Seecheck-locative-args
.If
locative-type-and-lambda-list
is a single symbol, then that's interpreted aslocative-type
, andlambda-list
isnil
.locative-supertypes
is a list of locative types whosedref-class
es are added to prepended to the list of superclasses this definition.
Locative types defined with
define-locative-type
can be listed withlisp-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 thatlocative-type
does not correspond to definitions in the running Lisp. Definitions with pseudo locatives are ofdtype
pseudo
and are not listed by default bydefinitions
.Locative types defined with
define-pseudo-locative-type
can be listed withpseudo-locative-types
.
[macro] define-locative-alias alias locative-type &body docstring
Define
alias
that can be substituted forlocative-type
(bothsymbol
s) for the purposes oflocate
ing.locative-type
must exist (i.e. be amonglocative-types
). For example, let's defineobject
as an alias of theclass
locative:(define-locative-alias object class)
Then,
locate
ing withobject
will find theclass
:(dref 'xref 'object) ==> #<DREF XREF CLASS>
The
locative-args
ofobject
(none in the above) are passed on toclass
.(arglist (dref 'object 'locative)) => (&REST ARGS) => :DESTRUCTURING
Note that
locative-aliases
are notlocative-types
and are not validdtype
s.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 thingslocate
able withlocative-type
are going to be symbols defined with a definer defined withdefine-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 thedefine-direction
form above.The
dref-class
of the defined locative type inherits fromsymbol-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
name
that can be used to attach a lambda list, documentation, and source location to a symbol in the context oflocative-type
. The defined macro's arglist is(symbol lambda-list &optional docstring)
.locative-type
is assumed to have been defined withdefine-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
object
argument oflocate
is 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
object
is anxref
(0
1
), then the lookup for (xref-locative-type
object
) is invoked. For anxref
with the locative(method () (number))
, this would be the lookup defined as(define-lookup method (name locative-args) ...)
With locator search
Else,
object
is a normal Lisp object, such as amethod
object fromfind-method
. The first oflisp-locative-types
whose 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
method
locative type and takes an argument namedobj
of classmethod
(which is like a specializer indefmethod
).lisp-locative-types
are 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
dtypep
answer 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 NIL (T FOO))>
For even more background, also note that if the name remains the same but locative args change, then
dtypep
can simply check withdref
if 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
locate
calls. 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
nil
or adref
(0
1
). Alternatively,locate-error
(0
1
) may be signalled.If a
dref
is returned, then itsdref-locative-type
must belocative-type
, and its class must be thedref-class
oflocative-type
.locative-args
must be congruent with the destructuring lambda list in the definition oflocative-type
.
[macro] define-lookup locative-type (name locative-args) &body body
Define a method of looking up definitions of
locative-type
with the givenlocative-args
. Lookups are invoked bylocate
when itsobject
argument is anxref
(0
1
) withlocative-type
but it is not adref
(0
1
), as in the case of(dref 'print 'function)
. When called, the variablesname
andlocative-args
are bound toxref-name
andxref-locative-args
of thexref
.locative-args
is validated withcheck-locative-args
beforebody
is evaluated.(define-lookup variable (name locative-args) (unless (special-variable-name-p name) (locate-error)) (make-instance 'variable-dref :name name :locative 'variable))
locative-type
is a valid locative type.name
andlocative-args
are bothsymbol
s.
The above are enforced at macro-expansion time.
body
must follow the rules in*check-locate*
.
[macro] call-lookup name locative-type locative-args
Call the lookup for
locative-type
withname
andlocative-args
.
[macro] define-locator locative-type ((object class)) &body body
Define a method of finding the definition with
locative-type
of instances ofclass
. When a locator'sbody
is evaluated,object
is bound to such an instance.(define-locator class ((class class)) (make-instance 'class-dref :name (class-name class) :locative 'class))
locative-type
is one oflisp-locative-types
. This is becausepseudo-locative-types
neverresolve
to first-class objects.object
is asymbol
.class
names aclass
that is not a subtype ofxref
. For how to convert definitions from one locative type to another, seedefine-cast
.
The above are enforced at macro-expansion time.
body
must follow the rules in*check-locate*
.
In contrast to when the Initial Definition is created from an
xref
(seedefine-lookup
), herelocative-args
are determined fromobject
.
[macro] call-locator object locative-type
Call the locator for
locative-type
withobject
.
[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'sbody
is evaluated,dref
is bound to an instancedref-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-type
is a valid locative type.If
locative-type
is one ofpseudo-locative-types
, thendref-class
must be of another pseudo locative type.dref-class
is either a direct downcast or an potentially non-direct upcast.Downcast: In this case,
locative-type
is one oflocative-type-direct-subs
of (dref-class-to-locative-type
dref-class
).Downcasting to non-direct subtypes is done in multiple steps. Consequently,the
body
of a downcast can rely on (class-of
dref
) beingclass
, not any subclass thereof.Upcast:
locative-type
is different but reachable from (dref-class-to-locative-type
dref-class
) by repeatedly choosing one oflocative-type-direct-supers
. Upcasting to non-direct supertypes is done in one step.
The above are enforced at macro-expansion time.
body
must 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-error
condition from the dynamic extent of alocate
call, that is, from thebody
s ofdefine-lookup
,define-locator
anddefine-cast
. It is an error to calllocate-error
elsewhere.format-control
, if non-nil
, is a format control for whichformat-args
are suitable.
[macro] check-locative-args locative-type locative-args
Signal a
locate-error
condition iflocative-args
do not match thelambda-list
argument oflocative-type
(not evaluated).
8.5 Extending Everything Else
[generic-function] resolve* dref
Return the object defined by the definition
dref
refers to. Signal aresolve-error
condition by calling theresolve-error
function if the lookup fails.To keep
resolve
a partial inverse oflocate
,define-locator
may be necessary forresolve
able definitions. This function is for extendingresolve
. 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-error
condition from the dynamic extent of aresolve*
method. It is an error to callresolve-error
elsewhere.format-and-args
, if non-nil
, is a format string and arguments suitable forformat
.
[generic-function] map-definitions-of-name fn name locative-type
Call
fn
withdref
s which can belocate
d with anxref
(0
1
) withname
,locative-type
and somelocative-args
. The strange wording here is because there may be multiple ways (and thusxref
s) 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 callsfn
with result ifdref
succeeds.fn
must not be called with the same (underxref=
) definition multiple times.This function is for extending
definitions
anddref-apropos
. Do not call it directly.
[generic-function] map-definitions-of-type fn locative-type
Call
fn
withdref
s which can belocate
d with anxref
(0
1
) withlocative-type
with somename
andlocative-args
.The default method forms
xref
s by combining each interned symbol as names withlocative-type
and nolocative-args
and callsfn
if itlocate
s a definition.fn
may be called withdref
s that arexref=
but differ in thexref
in theirdref-origin
.This function is for extending
dref-apropos
. Do not call it directly.
[generic-function] arglist* object
To extend
arglist
, specializeobject
on a normal Lisp type or on a subclass ofdref
.arglist
first callsarglist*
with itsobject
argument. If that doesn't work (i.e. the second value returned isnil
), then it callsarglist*
withobject
eitherresolve
d (if it's adref
) orlocate
d (if it's not adref
).The default method returns
nil
,nil
.There is also a method specialized on
dref
s, that looks up thedefinition-property
calledarglist
and returns its value withvalues-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
, specializeobject
on a normal Lisp type or on a subclass ofdref
.docstring
first callsdocstring*
with itsobject
argument. If that doesn't work (i.e.nil
is returned), then it callsdocstring*
withobject
eitherresolve
d (if it's adref
) orlocate
d (if it's not adref
).The default method returns
nil
.There is also a method specialized on
dref
s, that looks up thedefinition-property
calleddocstring
and returns its value withvalues-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
, specializeobject
on a normal Lisp type or on a subclass ofdref
.source-location
first callssource-location*
with itsobject
argument. If that doesn't work (i.e.nil
or(:error <message>)
is returned), then it callssource-location*
withobject
eitherresolve
d (if it's adref
) orlocate
d (if it's not adref
).source-location
returns the last of the(:error <message>)
s encountered or a generic error message if onlynil
s were returned.The default method returns
nil
.There is also a method specialized on
dref
s, that looks up thedefinition-property
calledsource-location
. If present, it must be a function of no arguments that returns a source location ornil
. 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
xref
whose name iseql
(0
1
) toindicator
. The second return value indicates whether the property was found.setf
able.
[function] delete-definition-property xref indicator
Delete the property associated with
xref
whose name iseql
(0
1
) toindicator
. Return true if the property was found.
[function] definition-properties xref
Return the properties of
xref
as 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-xref
withto-xref
, as if readding them one-by-one with(setf definition-property)
, and deleting them fromfrom-xref
withdelete-definition-property
.
8.6 dref-class
es
These are the dref-class
es 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-type
inherit 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
. Whensnippet
is provided, the match nearest tofile-position
is determined (see the Elispslime-isearch
andsource-location-adjusted-file-position
).
[function] source-location-p object
See if
object
is 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, iflocation
is 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
nil
if 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
nil
if there is no such Emacs buffer.
[function] source-location-buffer-position location
Return the position of the defining form in
source-location-buffer
ornil
if 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
nil
if it's not available.
[function] source-location-adjusted-file-position location
Return the actual file position
location
points to allowing for some deviation from the rawsource-location-file-position
, which is adjusted by searching for the nearest occurrence ofsource-location-snippet
in the file. Needless to say, this can be a very expensive operation.If
source-location-file
isnil
,nil
is returned. If there is no snippet, or it doesn't match, thensource-location-file-position
(or 0 if that'snil
) 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
.