All Manuals > LispWorks® User Guide and Reference Manual > 7 Dspecs: Tools for Handling Definitions

7.9 Users of location information

To find location information for definitions made in the running image or recorded in a tags database or a tags file:

The extent of the search is controlled by the value of the variable *active-finders*.

For example, to obtain the locations of the definitions of foo across all dspec namespaces, call:

(dspec:find-name-locations dspec:*dspec-classes* 'foo)

Another example of the use of find-name-locations is the LispWorks Editor tool's Find Definitions tab.

7.9.1 Finding definitions in the LispWorks editor

Returning to our example parameterdef definer:

(defmacro parameterdef  (value name)
 `(defparameter ,name ,value))
  1. Load a file foo.lisp containing:
    (parameterdef 42 *foo*)
    
  2. Now use Expression > Find Source on the symbol *foo*. Notice that LispWorks knows which file the definition is in, but cannot find the defining top level form.
  3. Also notice that the Definitions tab of the Editor tool does not display the definition of *foo*. This is because the Editor does not recognize parameterdef as a definer. When the LispWorks editor looks at the definitions in a buffer, it needs to know the dspecs that each defining form will generate when evaluated. You can tell the editor how to parse a defining form to generate the dspec by using define-form-parser.
  4. Now evaluate these forms to associate a parser with parameterdef and inform the dspec system that parameterdef is another way of naming a defparameter dspec:
    (dspec:define-form-parser parameterdef (value name)
      `(parameterdef ,name))
     
    (dspec:define-dspec-alias parameterdef (name)
      `(defparameter ,name))
    
  5. Now use Expression > Find Source on the symbol *foo* again. Notice that the source of the definition of *foo* is displayed correctly in the text tab of the Editor tool, and that the Definitions tab displays the definition as:
    (parameterdef *foo*)
    

7.9.2 Using pre-defined form parsers

LispWorks provides form parsers name-only-form-parser, single-form-form-parser and single-form-with-options-form-parser. You can use single-form-with-options-form-parser as the parser for my-defun definitions (see 7.3.2 Dspec aliases), like this:

(dspec:define-form-parser (my-defun
   (:parser dspec:single-form-with-options-form-parser)))

This allows the Editor to locate definitions like:

(my-defun (foo x y)
  (+ x y))

You can identify the form parser defined for a dspec class using get-form-parser.

7.9.3 The editor's implicit form parser

When testing your form parsers bear in mind that the LispWorks editor has an implicit form parser, independent of explicit parsers defined in the dspec system. It tries to parse a dspec from a top level form which is of length 2 or more and whose car has symbol name beginning with "DEF". That is:

(defxyz name forms)

gets parsed as:

(defxyz name)

which may be a dspec (and thus provides a match for the source location commands). This mechanism operates only when there's no explicit parser defined for defxyz.

The editor's implicit form parser is useful because it matches a common simple case. However it does not work for the parameterdef example, because that definer's symbol name does not begin with "DEF".

7.9.4 Reusing form parsers

The form parser established above was specifically for parameterdef forms. However if you have other definers of similar syntax - in this example, definers for which the name is the second subform - then you can define a form parser which can be associated with each of them, as follows:

(dspec:define-form-parser (name-second (:anonymous t)) 
    (value name)
  `(,name-second ,name))

This defines the function named name-second-form-parser as a form parser. Note that the name-second variable is evaluated in the body of the parser. Supposing you have another defining macro constantdef:

(defmacro constantdef (value name)
  `(defconstant ,name ,value))

then you can associate the same parser with both this and parameterdef:

(dspec:define-form-parser (parameterdef 
                           (:parser name-second-form-parser)))
 
(dspec:define-form-parser (constantdef 
                           (:parser name-second-form-parser)))

7.9.5 Example: defcondition

Suppose you have a macro based on define-condition:

(defmacro defcondition (&rest args)
  `(define-condition ,@args))

When the following form is evaluated, the system records the dspec (define-condition foo):

(defcondition foo () ())

Two setups are needed to allow the editor to locate such a defining form.

Firstly, this tells LispWorks to parse (defcondition ...) top level forms in the same way as it parses define-condition forms:

(dspec:define-form-parser
    (defcondition
     (:alias define-condition)))

So now:

(dspec:parse-form-dspec '(defcondition foo () ()))
=>
(defcondition foo)

Secondly, this tells the system that (defcondition foo) is an alias for (define-condition foo).

With this, the editor would report "Cannot find (DEFINE-CONDITION FOO) in ...".

(dspec:define-dspec-alias defcondition (name)
  `(define-condition ,name))

So now this definition can be located:

(defcondition foo () ())

just as if it were:

(define-condition foo () ())

7.9.6 Example: my-defmethod

Suppose you have a method definer my-defmethod:

(defmacro my-defmethod ((name &key doc)
                         lambda-list
                         &body body)
  `(defmethod ,name ,lambda-list ,@body))

Unlike function dspecs, method dspecs need to include the specialized argument types as well as the function name, so the alias and the parser both need to be more complex.

This causes the dspec to include the argument types:

(dspec:define-dspec-alias my-defmethod (name &rest options)
  `(defmethod ,name ,@options))

The dspec parser for method lambda lists is complicated, but you can invoke the defmethod parser in your my-defmethod parser, like this:

(dspec:define-form-parser my-defmethod (name-stuff lambda-list)
  `(,my-defmethod ,@(cdr (dspec:parse-form-dspec
                          `(defmethod ,(car name-stuff)
                                      ,lambda-list)))))

Now this definition can be located:

(my-defmethod (bar :doc "bar documentation") (x y)
  (foo x y))

just as if it were:

(defmethod bar (x y)
  (foo x y))

LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:19