# DRef Manual

###### \[in package DREF\]
## 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 XREF objects:

```common-lisp
(xref '*my-var* 'variable)
==> #<XREF *MY-VAR* VARIABLE>
```

XREFs just package up a @NAME (`*MY-VAR*`) and a
@LOCATIVE (VARIABLE). They need not denote existing definitions
until we actually want to use them:

```
(docstring (xref '*my-var* 'variable))
.. debugger invoked on LOCATE-ERROR:
..   Could not locate *MY-VAR* VARIABLE.
```

```common-lisp
(defvar *my-var* nil
  "This is my var.")

(docstring (xref '*my-var* 'variable))
=> "This is my var."
```

Behind the scenes, the DOCSTRING function LOCATEs the definition
corresponding to its XREF argument, turning it into a DREF:

```common-lisp
(locate (xref '*my-var* 'variable))
==> #<DREF *MY-VAR* VARIABLE>
```

Within DRef, the DREF-EXT::@DREF-SUBCLASSES form the basis of
extending DOCSTRING, SOURCE-LOCATION and ARGLIST. Outside DRef,
PAX makes PAX:DOCUMENT extensible through
PAX:DOCUMENT-OBJECT\*, which has methods specialized on DREFs.

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))>)
```

```common-lisp
(dref-apropos 'locate-error :package :dref :external-only t)
==> (#<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>)
```


## Locatives and 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 and DREF to construct a syntactically valid
  reference (matching the LAMBDA-LIST in the locative type's
  definition) that refers to an exisiting
  definition.

- RESOLVE to find the first-class (non-XREF) object the
  definition refers to, if any.

@OPERATIONS (ARGLIST, DOCSTRING, SOURCE-LOCATION) know how to deal
with references (discussed in the DREF-EXT::@EXTENDING-DREF).

- [class] XREF

    An XREF (cross-reference) 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 be
    malformed. The subclass DREF
    represents definitions that exist.

- [class] DREF XREF

    DREFs can be thought of as referring to
    definitions that actually exist, although changes in the system can
    invalidate them (for example, a DREF to a function definition can be
    invalidated by FMAKUNBOUND).
    
    DREFs must be created with LOCATE, and their purpose is to allow
    easy specialization of other generic functions (see
    DREF-EXT::@EXTENDING-DREF) and to confine locative validation to
    LOCATE.

- [function] XREF NAME LOCATIVE

    A shorthand for `(MAKE-INSTANCE 'XREF :NAME NAME :LOCATIVE LOCATIVE)`.
    It does no error checking: the LOCATIVE-TYPE of LOCATIVE-TYPE need
    not be defined, and the LOCATIVE-ARGS need not be valid. Use LOCATE
    or the DREF function to create DREF objects.

- [function] XREF= XREF1 XREF2

    See if XREF1 and XREF2 have the same XREF-NAME and XREF-LOCATIVE
    under EQUAL. Comparing like this makes most sense for
    DREFs. However, two XREFs different under XREF=
    may denote the same DREFs.

- [function] LOCATE OBJECT &OPTIONAL (ERRORP T)

    Return a DREF representing the definition given by the arguments.
    In the same dynamic environment, two DREFs denote the same
    thing if and only if they are XREF=.
    
    OBJECT must be a supported first-class object, a DREF, or an
    XREF:
    
    ```common-lisp
    (locate #'print)
    ==> #<DREF PRINT FUNCTION>
    ```
    
    ```common-lisp
    (locate (locate #'print))
    ==> #<DREF PRINT FUNCTION>
    ```
    
    ```common-lisp
    (locate (xref 'print 'function))
    ==> #<DREF PRINT FUNCTION>
    ```
    
    LOCATE-ERROR is signalled if OBJECT is an XREF with malformed
    LOCATIVE-ARGS, or if no corresponding definition is found. If ERRORP
    is NIL, then NIL and the LOCATE-ERROR condition are returned
    instead.
    
    ```common-lisp
    (locate (xref 'no-such-function 'function))
    .. debugger invoked on LOCATE-ERROR:
    ..   Could not locate NO-SUCH-FUNCTION FUNCTION.
    ..   NO-SUCH-FUNCTION is not a symbol naming a function.
    ```
    
    ```common-lisp
    (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.
    ```
    
    ```common-lisp
    (locate "xxx")
    .. debugger invoked on LOCATE-ERROR:
    ..   Could not locate "xxx".
    ```
    
    Use the low-level XREF to construct an XREF without error
    checking.
    
    Can be extended via LOCATE\*.

- [function] DREF NAME LOCATIVE &OPTIONAL (ERRORP T)

    Shorthand for `(LOCATE (XREF NAME LOCATIVE) ERRORP)`.

- [function] RESOLVE OBJECT &OPTIONAL (ERRORP T)

    If OBJECT is an XREF, then return the first-class object
    associated with its definition if any. Return OBJECT if it's not an
    XREF. Thus, the value returned is never an XREF.
    
    ```common-lisp
    (resolve (dref 'print 'function))
    ==> #<FUNCTION PRINT>
    ```
    
    ```common-lisp
    (resolve #'print)
    ==> #<FUNCTION PRINT>
    ```
    
    If OBJECT is an XREF, and the definition for it cannot be LOCATEd,
    then signal a LOCATE-ERROR condition.
    
    ```common-lisp
    (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 signal a RESOLVE-ERROR condition or return
    NIL depending on ERRORP:
    
    ```common-lisp
    (resolve (dref '*print-length* 'variable))
    .. debugger invoked on RESOLVE-ERROR:
    ..   Could not resolve *PRINT-LENGTH* VARIABLE.
    ```
    
    ```common-lisp
    (resolve (dref '*print-length* 'variable) nil)
    => NIL
    ```
    
    RESOLVE is a partial inverse of LOCATE: if a DREF is
    RESOLVEable, then LOCATEing the object it resolves to recovers the
    DREF equivalent to the original (XREF= and of the same type but not
    EQ).
    
    Can be extended via RESOLVE\*.

- [condition] LOCATE-ERROR ERROR

    Signalled by LOCATE when the definition cannot be
    found, and ERRORP is true.

- [condition] RESOLVE-ERROR ERROR

    Signalled by RESOLVE when the object defined cannot
    be returned, and ERRORP is true.

## Listing Definitions

- [function] DEFINITIONS NAME &KEY (LOCATIVE-TYPES (LISP-LOCATIVE-TYPES))

    Return all definitions of NAME that match LOCATIVE-TYPES
    as a list of DREFs.
    
    The DREF-NAMEs may not be the same as NAME, for example, when NAME
    is a package nickname:
    
    ```common-lisp
    (definitions 'pax)
    ==> (#<DREF "MGL-PAX" PACKAGE>)
    ```
    
    Can be extended via MAP-DEFINITIONS.

- [function] DREF-APROPOS NAME &KEY PACKAGE EXTERNAL-ONLY CASE-SENSITIVE (LOCATIVE-TYPES '(:LISP))

    Return a list of DREFs corresponding to existing
    definitions that match the various arguments. First, `(DREF-APROPOS
    NIL :LOCATIVE-TYPES NIL)` lists all definitions in the system.
    Arguments with non-NIL values filter the list of definitions.
    
    Roughly speaking, when NAME or PACKAGE is a SYMBOL, they must match
    the whole @NAME of the definition:
    
    ```common-lisp
    (dref-apropos 'method :package :dref :external-only t)
    ==> (#<DREF METHOD CLASS> #<DREF METHOD LOCATIVE>)
    ```
    
    On the other hand, when NAME or PACKAGE is a STRING, they are
    matched as substrings:
    
    ```common-lisp
    (dref-apropos "method" :package :dref :external-only t)
    ==> (#<DREF METHOD CLASS> #<DREF METHOD LOCATIVE>
    -->  #<DREF METHOD-COMBINATION CLASS> #<DREF METHOD-COMBINATION LOCATIVE>)
    ```
    
    The list of LOCATIVE-TYPES, if non-NIL, filters out definitions
    whose locative types are not listed:
    
    ```common-lisp
    (dref-apropos "method" :package :dref :external-only t
                  :locative-types '(class))
    ==> (#<DREF METHOD CLASS> #<DREF METHOD-COMBINATION CLASS>)
    ```
    
    In the list, the special keywords :ALL, :LISP, :PSEUDO match all
    LOCATIVE-TYPES, LISP-LOCATIVE-TYPES and PSEUDO-LOCATIVE-TYPES,
    respectively.
    
    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)` with `P`. Note that
    PRINC-TO-STRING does not print the package of symbols. We say that
    two strings *match* if CASE-SENSITIVE is NIL and they are EQUALP, or
    CASE-SENSITIVE is true and they are EQUAL. CASE-SENSITIVE affects
    *substring* comparisons too.
    
    - If NAME is a SYMBOL, then its SYMBOL-NAME must *match* `P`.
    
    - If NAME is a STRING, then it must be a *substring* of `P`.
    
    - If PACKAGE is :NONE, then `C` must *not* be a SYMBOL.
    
    - If PACKAGE is not NIL or :NONE, then `C` must be a symbol.
    
    - If PACKAGE is a PACKAGE, it must be EQ to the
      SYMBOL-PACKAGE of `C`.
    
    - If PACKAGE is a SYMBOL other than :NONE, then its SYMBOL-NAME must
      *match* the PACKAGE-NAME or one of the PACKAGE-NICKNAMES of
      SYMBOL-PACKAGE of `C`.
    
    - If PACKAGE is a STRING, then it must be a *substring* of the
      PACKAGE-NAME of SYMBOL-PACKAGE of `C`.
    
    - If EXTERNAL-ONLY and `C` is a symbol, then `C` must be external in
      a matching package.
    
    - If LOCATIVE-TYPES is NIL, then it matches everything.
    
    - If LOCATIVE-TYPEs is non-NIL, then the LOCATIVE-TYPE of the
      candidate definition must be in it (handling :ALL,
      :LISP, and :PSEUDO as described above).
    
    Can be extended via MAP-NAMES.

- [function] LOCATIVE-TYPES

    Return a list of non-alias locative types.
    This is the UNION of LISP-LOCATIVE-TYPES and PSEUDO-LOCATIVE-TYPES.

- [function] LISP-LOCATIVE-TYPES

    Return the locative types that correspond to Lisp definitions
    except UNKNOWN. These are the ones defined with
    DEFINE-LOCATIVE-TYPE.

- [function] PSEUDO-LOCATIVE-TYPES

    Return the locative types that correspond to non-Lisp definitions
    plus UNKNOWN. These are the ones defined with
    DEFINE-PSEUDO-LOCATIVE-TYPE.

- [function] LOCATIVE-ALIASES

    Return the list of locatives aliases, defined with DEFINE-LOCATIVE-ALIAS.

## Operations

The following functions take a single object definition as their argument.
They may try to LOCATE the definition of the object, which may
signal a LOCATE-ERROR condition.

- [function] ARGLIST OBJECT

    Return the arglist of the definition of OBJECT or NIL if the
    arglist cannot be determined.
    
    The second return value indicates whether the arglist has been
    found. Furthermore, :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.
    
    ```common-lisp
    (arglist #'arglist)
    => (OBJECT)
    => :ORDINARY
    ```
    
    ```common-lisp
    (arglist (dref 'define-locative-type 'macro))
    => (LOCATIVE-TYPE LAMBDA-LIST &BODY DOCSTRING)
    => :MACRO
    ```
    
    ```common-lisp
    (arglist (dref 'method 'locative))
    => (METHOD-QUALIFIERS METHOD-SPECIALIZERS)
    => :DESTRUCTURING
    ```
    
    This function supports MACROs, COMPILER-MACROs, SETF functions,
    FUNCTIONs, GENERIC-FUNCTIONs, METHODs, TYPES, LOCATIVEs. Note that
    ARGLIST depends on the quality of SWANK-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 or NIL if it cannot be determined (this
    is used by PAX:DOCUMENT when PAX::@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-MACRO docstrings on ABCL, AllegroCL, CCL, ECL;
    
    - METHOD-COMBINATION docstrings on ABCL, AllegroCL.
    
    Can be extended via DOCSTRING\*.

- [function] SOURCE-LOCATION OBJECT &KEY ERRORP

    Return the Swank source location for the defining form
    of OBJECT. If no source location was found, then either an ERROR
    condition is signalled if ERRORP else the ERROR is
    returned as the second value (with the first being NIL). The
    returned Swank location object is to be accessed only through the
    DREF-EXT::@SOURCE-LOCATIONS API or to be passed to e.g Slime's
    `slime-goto-source-location`.
    
    Note that the availability of source location information varies
    greatly across Lisp implementations.
    
    Can be extended via SOURCE-LOCATION\*.

## 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

```common-lisp
(resolve (dref 'print 'function))
==> #<FUNCTION PRINT>
```

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.

### Locatives for Variables

- [locative] VARIABLE &OPTIONAL INITFORM

    Refers to a global special variable.
    INITFORM, or if not specified, the global value of the variable is
    to be used for @PRESENTATION.
    
    ```common-lisp
    (dref '*print-length* 'variable)
    ==> #<DREF *PRINT-LENGTH* VARIABLE>
    ```
    
    VARIABLE references do not RESOLVE.

- [locative] CONSTANT &OPTIONAL INITFORM

    Refers to a constant variable defined with DEFCONSTANT. INITFORM,
    or if not specified, the value of the constant is included in the
    documentation. The CONSTANT locative is like the VARIABLE locative,
    but it also checks that its object is CONSTANTP.
    
    CONSTANT references do not RESOLVE.

### Locatives for Macros

- [locative] MACRO

    Refers to a global macro, typically defined with DEFMACRO, or to a
    special operator.
    
    MACRO references do not RESOLVE.

- [locative] SYMBOL-MACRO

    Refers to a global symbol macro, defined with DEFINE-SYMBOL-MACRO.
    Note that since DEFINE-SYMBOL-MACRO does not support docstrings, PAX
    defines methods on the DOCUMENTATION 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 not RESOLVE.

- [locative] COMPILER-MACRO

    Refers to a compiler macro, typically defined with
    DEFINE-COMPILER-MACRO.
    
    COMPILER-MACRO references do not RESOLVE.

- [locative] SETF &OPTIONAL METHOD

    Refers to a setf expander (see DEFSETF and DEFINE-SETF-EXPANDER)
    or a setf function (e.g. `(DEFUN (SETF NAME) ...)` or the
    same with DEFGENERIC). The format in DEFSECTION is `(<NAME> SETF)`
    in all these cases.
    
    To refer to methods of a setf generic function, use a METHOD
    locative inside SETF like this:
    
        (dref 'documentation '(setf (method () (t symbol (eql function))))
    
    References to setf functions RESOLVE to the function object. Setf
    expander references do not RESOLVE.

### Locatives for Functions

- [locative] FUNCTION

    Refers to a global function, typically defined with DEFUN. The
    @NAME must be a SYMBOL (see the SETF locative for how to reference
    setf functions). It is also allowed to reference
    GENERIC-FUNCTIONs as FUNCTIONs:
    
    ```common-lisp
    (dref 'docstring 'function)
    ==> #<DREF DOCSTRING FUNCTION>
    ```


- [locative] GENERIC-FUNCTION

    Refers to a GENERIC-FUNCTION, typically defined with
    DEFGENERIC. The @NAME must be a SYMBOL (see the SETF locative for
    how to reference setf functions).

- [locative] METHOD METHOD-QUALIFIERS METHOD-SPECIALIZERS

    Refers to METHODs named by SYMBOLs (for SETF methods,
    see the SETF locative). METHOD-QUALIFIERS and METHOD-SPECIALIZERS
    are similar to the CL:FIND-METHOD's arguments of the same names. For
    example, the method
    
    ```common-lisp
    (defgeneric foo-gf (x y z)
      (:method :around (x (y (eql 'xxx)) (z string))
        (values x y z)))
    ```
    
    can be referred to as
    
    ```common-lisp
    (dref 'foo-gf '(method (:around) (t (eql xxx) string)))
    ==> #<DREF FOO-GF (METHOD (:AROUND) (T (EQL XXX) STRING))>
    ```
    
    METHOD is not EXPORTABLE-LOCATIVE-TYPE-P.

- [locative] METHOD-COMBINATION

    Refers to a METHOD-COMBINATION, defined with
    DEFINE-METHOD-COMBINATION.
    
    METHOD-COMBINATION references do not RESOLVE.

- [locative] ACCESSOR CLASS-NAME

    Refers to an :ACCESSOR in a DEFCLASS:
    
    ```common-lisp
    (defclass foo ()
      ((xxx :accessor foo-xxx)))
    
    (dref 'foo-xxx '(accessor foo))
    ==> #<DREF FOO-XXX (ACCESSOR FOO)>
    ```
    
    An :ACCESSOR in DEFCLASS creates a reader and a writer method.
    Somewhat arbitrarily, ACCESSOR references RESOLVE to the writer
    method but can be LOCATEd with either.

- [locative] READER CLASS-NAME

    Like ACCESSOR, but refers to a :READER method in a DEFCLASS.

- [locative] WRITER CLASS-NAME

    Like ACCESSOR, but refers to a :WRITER method in a DEFCLASS.

- [locative] STRUCTURE-ACCESSOR &OPTIONAL STRUCTURE-CLASS-NAME

    Refers to an accessor function generated by DEFSTRUCT.
    A LOCATE-ERROR condition is signalled if the wrong
    STRUCTURE-CLASS-NAME is provided.
    
    Note that there is no portable way to detect structure accessors,
    and on some platforms, `(LOCATE #'MY-ACCESSOR)`, DEFINITIONS and
    DREF-APROPOS will return FUNCTION references instead. On such
    platforms, STRUCTURE-ACCESSOR references do not RESOLVE.

### Locatives for Types and Declarations

- [locative] TYPE

    This locative can refer to any Lisp type and compound type
    specifiers such as AND. For types defined with
    DEFTYPE, their ARGLIST is available. CLASSes and
    CONDITIONs may be referred to as TYPEs:
    
    ```common-lisp
    (dref 'xref 'type)
    ==> #<DREF XREF CLASS>
    ```
    
    ```common-lisp
    (dref 'locate-error 'type)
    ==> #<DREF LOCATE-ERROR CONDITION>
    ```
    
    TYPE references do not RESOLVE.

- [locative] CLASS

    Naturally, CLASS is the locative type for CLASSes.
    CONDITIONs may be referred to as CLASSes:
    
    ```common-lisp
    (dref 'locate-error 'class)
    ==> #<DREF LOCATE-ERROR CONDITION>
    ```


- [locative] DECLARATION

    Refers to a declaration, used in DECLARE, DECLAIM and PROCLAIM.
    
    User code may also define new declarations with CLTL2 functionality,
    but there is currently no way to provide a docstring, and their
    ARGLIST is always NIL.
    
    ```
    (cl-environments:define-declaration my-decl (&rest things)
      (values :declare (cons 'foo things)))
    ```
    
    DECLARATION references do not RESOLVE.
    
    Also, SOURCE-LOCATION on declarations currently only works on SBCL.

### Locatives for the Condition System

- [locative] CONDITION

    CONDITION is the locative type for CONDITIONs.

- [locative] RESTART

    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 with
    DEFINE-RESTART:
    
    ```common-lisp
    (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.

### Locatives for Packages and Readtables

- [locative] ASDF/SYSTEM:SYSTEM

    Refers to a registered ASDF:SYSTEM.
    The @NAME may be anything ASDF:FIND-SYSTEM supports.
    
    ASDF:SYSTEM is not EXPORTABLE-LOCATIVE-TYPE-P.

- [locative] PACKAGE

    Refers to a PACKAGE, defined by DEFPACKAGE or MAKE-PACKAGE.
    The @NAME may be anything FIND-PACKAGE supports.
    
    PACKAGE is not EXPORTABLE-LOCATIVE-TYPE-P.

- [locative] READTABLE

    Refers to a named READTABLE defined with
    NAMED-READTABLES:DEFREADTABLE, which associates a global name and a
    docstring with the readtable object. The @NAME may be anything
    FIND-READTABLE supports. Unfortunately, SOURCE-LOCATION information
    is not available.
    
    READTABLE references RESOLVE to FIND-READTABLE on their @NAME.

### DRef Locatives

- [locative] LOCATIVE

    This is the locative for @LOCATIVE-TYPEs defined with
    DEFINE-LOCATIVE-TYPE, DEFINE-PSEUDO-LOCATIVE-TYPE and
    DEFINE-LOCATIVE-ALIAS.
    
    ```
    (first-line (source-location-snippet
                 (source-location (dref 'macro 'locative))))
    => "(define-locative-type macro ()"
    ```


- [locative] UNKNOWN DSPEC

    This pseudo locative type is to allow PAX
    to work in a limited way with locatives it doesn't know. UNKNOWN
    definitions 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
    UNKNOWN locative on SBCL.
    
    ```common-lisp
    (definitions 'double-float :locative-types (locative-types))
    ==> (#<DREF DOUBLE-FLOAT CLASS> #<DREF DOUBLE-FLOAT (CLHS TYPE)>
    -->  #<DREF DOUBLE-FLOAT (UNKNOWN (:DEFINE-ALIEN-TYPE DOUBLE-FLOAT))>)
    ```
    
    ```common-lisp
    (dref 'double-float '(unknown (:define-alien-type double-float)))
    ==> #<DREF DOUBLE-FLOAT (UNKNOWN (:DEFINE-ALIEN-TYPE DOUBLE-FLOAT))>
    ```
    
    ARGLIST and DOCSTRING return NIL for UNKNOWNs, but SOURCE-LOCATION
    works.

- [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 and SOURCE-LOCATION in the locative itself. See
    MAKE-SOURCE-LOCATION for the description of FILE, FILE-POSITION, and
    SNIPPET. LAMBDA references do not RESOLVE. The @NAME must be NIL.
    
    ```common-lisp
    (arglist (dref nil '(lambda :arglist ((x y) z)
                                       :arglist-type :macro)))
    => ((X Y) Z)
    => :MACRO
    ```
    
    ```common-lisp
    (docstring (dref nil '(lambda :docstring "xxx"
                                         :docstring-package :dref)))
    => "xxx"
    ==> #<PACKAGE "DREF">
    ```
    
    ```common-lisp
    (source-location-file
     (source-location (dref nil '(lambda :file "xxx.el"))))
    => "xxx.el"
    ```
    
    See the PAX:INCLUDE locative for an example.

## Glossary

- [glossary-term] name

    Names are symbols or strings which name functions, types, packages,
    etc. Together with @LOCATIVEs, they form @REFERENCEs.
    
    See XREF-NAME and DREF-NAME.

- [glossary-term] locative

    Locatives specify a *type* of definition such as
    FUNCTION or VARIABLE and together with
    @NAMEs form @REFERENCEs.
    
    A locative can be a symbol or a list whose CAR is a symbol. In
    either case, the symbol is called the @LOCATIVE-TYPE, and the rest
    of the elements are the *locative arguments* (for example, see the
    METHOD locative).
    
    See XREF-LOCATIVE and DREF-LOCATIVE.

- [glossary-term] locative type

    The locative type is the part of a @LOCATIVE that identifies
    what kind definition is being referred to. See @LOCATIVE-TYPES for
    the list locative types built into DRef.
    
    Locative types are similar to Lisp namespaces.
    
    See XREF-LOCATIVE-TYPE and DREF-LOCATIVE-TYPE.

- [glossary-term] reference

    A reference is an @NAME plus a @LOCATIVE, and it identifies a
    possible definition. References are of class XREF. When a reference
    is a DREF, it may also be called a definition.

- [glossary-term] presentation

    @REFERENCEs may have arguments (see
    DREF-EXT::@ADDING-NEW-LOCATIVES) that do not affect the behaviour of
    LOCATE and the standard DRef @OPERATIONS, but which may be used for
    other, "presentation" purposes. For example, the VARIABLE
    locative's INITFORM argument is used for presentation by
    PAX:DOCUMENT. Presentation arguments are available via
    DREF-EXT:DREF-ORIGIN.

## Extending DRef

### References

- [reader] XREF-NAME XREF (:NAME)

    The @NAME of the reference.

- [reader] XREF-LOCATIVE XREF (:LOCATIVE)

    The @LOCATIVE of the reference.
    
    The locative is normalized by replacing single-element lists with
     their only element:
    
    ```common-lisp
    (xref 'print 'function)
    ==> #<XREF PRINT FUNCTION>
    ```
    
    ```common-lisp
    (xref 'print '(function))
    ==> #<XREF PRINT FUNCTION>
    ```


- [reader] DREF-NAME DREF

    The same as XREF-NAME, but only works on
    DREFs. Use it as a statement of intent.

- [reader] DREF-LOCATIVE DREF

    The same as XREF-LOCATIVE, but only works on
    DREFs. Use it as a statement of intent.

- [reader] DREF-ORIGIN DREF

    The object from which LOCATE constructed this
    DREF. This is an XREF when the LOCATIVE argument
    to LOCATE was non-NIL and the value NAME-OR-OBJECT argument
    otherwise. DREF-ORIGIN may have @PRESENTATION arguments, which are
    not included in LOCATIVE-ARGS as is the case with INITFORM
    argument of the VARIABLE locative:
    
    ```common-lisp
    (dref '*standard-output* '(variable "see-below"))
    ==> #<DREF *STANDARD-OUTPUT* VARIABLE>
    ```
    
    ```common-lisp
    (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's PAX:DOCUMENTed:
    
    ```common-lisp
    (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 LOCATIVE (which may be from
    XREF-LOCATIVE). This is the first element of LOCATIVE if it's a
    list. If it's a symbol, it's that symbol itself.

- [function] LOCATIVE-ARGS LOCATIVE

    Return the REST of LOCATIVE (which may be from XREF-LOCATIVE)
    if it's a list. If it's a symbol, then return NIL. The locative args
    should match the LAMBDA-LIST of the LOCATIVE-TYPE's
    definition, but this is guaranteed only for
    locatives of DREFs and is not checked for plain
    XREFs.

The following convenience functions are compositions of
{`LOCATIVE-TYPE`, `LOCATIVE-ARGS`} and {`XREF-LOCATIVE`,
`DREF-LOCATIVE`}.

- [function] XREF-LOCATIVE-TYPE XREF

- [function] XREF-LOCATIVE-ARGS XREF

- [function] DREF-LOCATIVE-TYPE DREF

- [function] DREF-LOCATIVE-ARGS DREF

### Adding New Locatives

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 ()
  "Naturally, CLASS is the locative type for [CLASS][class]es.
  [CONDITIONs][type] may be referred to as CLASSes:

  ```cl-transcript
  (dref 'locate-error 'class)
  ==> #<DREF LOCATE-ERROR CONDITION>
  ```")

```

Next, we define a subclass of DREF associated with the
CLASS locative type and specialize LOCATE\*:

```
(define-definition-class class class-dref)

(defmethod locate* ((class class))
  (make-instance 'class-dref :name (class-name class) :locative 'class))

(defmethod dref* (symbol (locative-type (eql 'class)) locative-args)
  (check-locative-args class 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))

```

The first method makes `(LOCATE (FIND-CLASS 'DREF))` work, while
the second is for `(DREF 'DREF 'CLASS)`. Naturally, for locative
types that do not define first-class objects, the first method
cannot be defined.

Then, with ADD-DREF-ACTUALIZER, we install a function that that runs
whenever a new DREF is about to be returned from LOCATE and
turn the locative TYPE into the locative CLASS if the denoted
definition is of a class:

```
(defun actualize-type-to-class (dref)
  (when (eq (dref-locative-type dref) 'type)
    (dref (dref-name dref) 'class nil)))

(add-dref-actualizer 'actualize-type-to-class)

```

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.

- [macro] DEFINE-LOCATIVE-TYPE LOCATIVE-TYPE LAMBDA-LIST &BODY DOCSTRING

    Declare LOCATIVE-TYPE as a LOCATIVE, which is the
    first step in DREF-EXT::@EXTENDING-DREF.
    
    LAMBDA-LIST is a destructuring lambda list. The
    LOCATIVE-ARGS of DREFs with @LOCATIVE-TYPE
    LOCATIVE-TYPE (the argument given to this macro) always conform to
    this lambda list. See CHECK-LOCATIVE-ARGS.
    
    For example, if  have:
    
    ```
    (define-locative-type dummy (x &key y)
      "Dummy docstring.")
    ```
    
    then `(LOCATE 'DUMMY 'LOCATIVE)` refers to this definition. That is,
    ARGLIST, DOCSTRING and SOURCE-LOCATION all work on it.
    
    Locative types defined with DEFINE-LOCATIVE-TYPE can be listed with
    LISP-LOCATIVE-TYPES.

- [macro] DEFINE-PSEUDO-LOCATIVE-TYPE LOCATIVE-TYPE LAMBDA-LIST &BODY DOCSTRING

    Like DEFINE-LOCATIVE-TYPE, but declare that LOCATIVE-TYPE does
    not correspond to definitions in the Lisp system. Definitions with
    pseduo locatives are not listed by default by DEFINITIONS.
    
    Locative types defined with DEFINE-PSEUDO-LOCATIVE-TYPE can be
    listed with PSEUDO-LOCATIVE-TYPES.

- [macro] DEFINE-LOCATIVE-ALIAS ALIAS LOCATIVE-TYPE &BODY DOCSTRING

    Define ALIAS as a locative equivalent to LOCATIVE-TYPE (both
    SYMBOLs). LOCATIVE-TYPE must exist (i.e. be among LOCATIVE-TYPES).
    For example, let's define OBJECT as an alias of the CLASS locative:
    
    ```common-lisp
    (define-locative-alias object class)
    ```
    
    Then, LOCATEing with OBJECT will find the CLASS:
    
    ```common-lisp
    (dref 'xref 'object)
    ==> #<DREF XREF CLASS>
    ```
    
    The LOCATIVE-ARGS of OBJECT (none in the above) are passed on to
    CLASS.
    
    ```common-lisp
    (arglist (dref 'object 'locative))
    => (&REST ARGS)
    => :DESTRUCTURING
    ```
    
    Also, see PAX::@LOCATIVE-ALIASES in PAX.

- [macro] DEFINE-DEFINITION-CLASS LOCATIVE-TYPE CLASS-NAME &OPTIONAL (SUPERCLASSES '(DREF)) &BODY BODY

    Define a subclass of DREF. All definitions with LOCATIVE-TYPE
    must be of this type. If non-NIL, BODY is DEFCLASS' slot definitions
    and other options.

- [generic-function] LOCATE* OBJECT

    Return a definition of OBJECT as a DREF,
    without actualizing it. If OBJECT is a DREF
    already, then this function simply returns it. If no definition is
    found for OBJECT, then LOCATE-ERROR is signalled.
    
    This function is for extending LOCATE. Do not call it directly.

- [generic-function] DREF* NAME LOCATIVE-TYPE LOCATIVE-ARGS

    LOCATE\* calls this for XREFs which are not
    DREFs.
    
    An EQL-specialized method must be defined for all new locative
    types. This function is for extending LOCATE. Do not call it
    directly.

- [macro] CHECK-LOCATIVE-ARGS LOCATIVE-TYPE LOCATIVE-ARGS

    Signal a LOCATE-ERROR condition if LOCATIVE-ARGS do not match the
    LAMBDA-LIST argument of LOCATIVE-TYPE (not evaluated).

- [function] LOCATE-ERROR &REST FORMAT-AND-ARGS

    Call this function to signal a LOCATE-ERROR condition from the
    dynamic extent of a LOCATE\* method (which includes
    DREF\*). It is an error to call LOCATE-ERROR elsewhere.
    
    FORMAT-AND-ARGS, if non-NIL, is a format string and arguments
    suitable for FORMAT.

- [function] ADD-DREF-ACTUALIZER NAME

    Add the global function denoted by the symbol NAME to the list
    of actualizers. Actualizers are functions of a single DREF
    argument. They are called within LOCATE when LOCATE\* returns a DREF.
    Their job is to make the DREF more specific.

- [function] REMOVE-DREF-ACTUALIZER NAME

    Remove the global function denoted by the symbol NAME from the
    list of actualizers.

- [generic-function] RESOLVE* DREF

    Return the object defined by the definition DREF
    refers to. Signal a RESOLVE-ERROR condition by calling the
    RESOLVE-ERROR function if the lookup fails.
    
    To keep RESOLVE a partial inverse of LOCATE, a specialized LOCATE\*
    method or an actualizer must be defined 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-ERROR condition from the
    dynamic extent of a RESOLVE\* method. It is an error to call
    RESOLVE-ERROR elsewhere.
    
    FORMAT-AND-ARGS, if non-NIL, is a format string and arguments
    suitable for FORMAT.

- [generic-function] MAP-DEFINITIONS FN NAME LOCATIVE-TYPE

    Call FN with DREFs which have the given
    NAME and LOCATIVE-TYPE. For most locative types, there is at most
    one definition, but for METHOD, for example, there may be many. The
    default method simply does `(DREF NAME LOCATIVE-TYPE NIL)` and calls
    FN with result if DREF succeeds.
    
    This function is for extending DEFINITIONS. Do not call it directly.

- [generic-function] MAP-NAMES FN LOCATIVE-TYPE

    Call FN with @NAMEs that form a DREF with
    some locative with LOCATIVE-TYPE. The default method tries to form
    DREFs by combining each interned symbol with LOCATIVE-TYPE and no
    LOCATIVE-ARGS.
    
    This function is for extending DREF-APROPOS. Do not call it
    directly.

- [generic-function] ARGLIST* OBJECT

    To extend ARGLIST, specialize this on a subclass of
    DREF if that subclass is not RESOLVEable, else on the type
    of object it resolves to. This function is for extension only. Do
    not call it directly.

- [generic-function] DOCSTRING* DREF

    To extend DOCSTRING, specialize this on a subclass
    of DREF if that subclass is not RESOLVEable, else on the
    type of object it resolves to. This function is for extension only.
    Do not call it directly.

- [generic-function] SOURCE-LOCATION* DREF

    To extend SOURCE-LOCATION, specialize this on a
    subclass of DREF if that subclass is not RESOLVEable, else
    on the type of object it resolves to. This function is for extension
    only. Do not call it directly.

### 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 LAMBDA-LIST &BODY DOCSTRING

    Similar to DEFINE-LOCATIVE-TYPE, but it assumes that all things
    LOCATEable with LOCATIVE-TYPE are 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-DIRECTION` form above.

- [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 of
    LOCATIVE-TYPE. The defined macro's arglist is `(SYMBOL LAMBDA-LIST
    &OPTIONAL DOCSTRING)`. LOCATIVE-TYPE is assumed to have been defined
    with DEFINE-SYMBOL-LOCATIVE-TYPE.

### DREF Subclasses

These are the DREF subclasses corresponding to
DREF::@LOCATIVE-TYPES. They are exported to make it possible to go
beyond the standard @OPERATIONS (e.g. PAX:DOCUMENT-OBJECT\*) and for
subclassing.

**for Variables**

- [class] VARIABLE-DREF DREF

- [class] CONSTANT-DREF VARIABLE-DREF

**for Macros**

- [class] MACRO-DREF DREF

- [class] SYMBOL-MACRO-DREF DREF

- [class] COMPILER-MACRO-DREF DREF

- [class] SETF-DREF DREF

**for Functions**

- [class] FUNCTION-DREF DREF

- [class] GENERIC-FUNCTION-DREF FUNCTION-DREF

- [class] METHOD-DREF DREF

- [class] METHOD-COMBINATION-DREF DREF

- [class] ACCESSOR-DREF DREF

- [class] READER-DREF DREF

- [class] WRITER-DREF DREF

- [class] STRUCTURE-ACCESSOR-DREF DREF

**for Types and Declarations**

- [class] TYPE-DREF DREF

- [class] CLASS-DREF DREF

- [class] DECLARATION-DREF DREF

**for the Condition System**

- [class] CONDITION-DREF CLASS-DREF

- [class] RESTART-DREF SYMBOL-LOCATIVE-DREF

**for Packages and Readtables**

- [class] ASDF-SYSTEM-DREF DREF

- [class] PACKAGE-DREF DREF

- [class] READTABLE-DREF DREF

**for DRef Locatives**

- [class] LOCATIVE-DREF DREF

- [class] SYMBOL-LOCATIVE-DREF DREF

- [class] UNKNOWN-DREF DREF

- [class] LAMBDA-DREF DREF

### 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 SNIPPET is provided, the match nearest to FILE-POSITION is
    determined (see the Elisp `slime-isearch` and
    SOURCE-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, if LOCATION 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 or NIL 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 raw SOURCE-LOCATION-FILE-POSITION, which is
    adjusted by searching for the nearest occurrence of
    SOURCE-LOCATION-SNIPPET in the file. Needless to say, this can be a
    very expensive operation.
    
    If SOURCE-LOCATION-FILE is NIL, NIL is 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.

* * *
###### \[generated by [MGL-PAX](https://github.com/melisgl/mgl-pax)\]
