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.
Returning to our example parameterdef definer
(defmacro parameterdef (value name)
`(defparameter ,name ,value))
foo.lisp
containing*foo*
. Notice that LispWorks knows which file the definition is in, but cannot find the defining top level form.*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.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))
*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*)
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 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.
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)
(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"
.
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))
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)))
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 the system how to parse (defcondition ...) toplevel forms:
(dspec:define-form-parser
(defcondition
(:alias define-condition)))
(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 () ())
(define-condition foo () ())
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))
(defmethod bar (x y)
(foo x y))
LispWorks User Guide and Reference Manual - 20 Sep 2017