Function: elisp-scope-analyze-form
elisp-scope-analyze-form is an autoloaded and byte-compiled function
defined in elisp-scope.el.gz.
Signature
(elisp-scope-analyze-form CALLBACK &optional STREAM)
Documentation
Read and analyze code from STREAM, reporting findings via CALLBACK.
Call CALLBACK for each analyzed symbol SYM with arguments ROLE, POS, SYM, ID and DEF, where ROLE is a symbol that specifies the semantics of SYM; POS is the position of SYM in STREAM; ID is an object that uniquely identifies (co-)occurrences of SYM in the current defun; and DEF is the position in which SYM is locally defined, or nil. If SYM is itself a binding occurrence, then POS and DEF are equal. If SYM is not lexically bound, then DEF is nil.
If STREAM is nil, it defaults to the current buffer. When reading from the current buffer, this function leaves point at the end of the form.
This function recursively analyzes Lisp forms (HEAD . TAIL), usually starting with a top-level form, by inspecting HEAD at each level:
- If HEAD is a symbol with a non-nil elisp-scope-analyzer symbol
property, then the value of that property specifies a bespoke analyzer
function, AF, that is called as (AF HEAD . TAIL) to analyze the form.
See more details about writing analyzer functions below.
- If HEAD satisfies functionp, which means it is a function in the
running Emacs session, analyze the form as a function call.
- If HEAD is a safe macro (see elisp-scope-safe-macro-p), expand it
and analyze the resulting form.
- If HEAD is unknown, then the arguments in TAIL are ignored, unless
elisp-scope-assume-func is non-nil, in which case they are analyzed
as evaluated forms (i.e. HEAD is assumed to be a function).
An analyzer (function specified via the elisp-scope-analyzer property)
can use the functions elisp-scope-report-s, elisp-scope-1 and
elisp-scope-n to analyze its arguments, and it can consult the
variable elisp-scope-output-spec to obtain the expected output spec of
the analyzed form. For example, the following is a suitable analyzer
for the identity function:
(lambda (fsym arg)
(elisp-scope-report-s fsym 'function)
(elisp-scope-1 arg elisp-scope-output-spec))
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/elisp-scope.el.gz
;;;###autoload
(defun elisp-scope-analyze-form (callback &optional stream)
"Read and analyze code from STREAM, reporting findings via CALLBACK.
Call CALLBACK for each analyzed symbol SYM with arguments ROLE, POS,
SYM, ID and DEF, where ROLE is a symbol that specifies the semantics of
SYM; POS is the position of SYM in STREAM; ID is an object that uniquely
identifies (co-)occurrences of SYM in the current defun; and DEF is the
position in which SYM is locally defined, or nil. If SYM is itself a
binding occurrence, then POS and DEF are equal. If SYM is not lexically
bound, then DEF is nil.
If STREAM is nil, it defaults to the current buffer. When reading from
the current buffer, this function leaves point at the end of the form.
This function recursively analyzes Lisp forms (HEAD . TAIL), usually
starting with a top-level form, by inspecting HEAD at each level:
- If HEAD is a symbol with a non-nil `elisp-scope-analyzer' symbol
property, then the value of that property specifies a bespoke analyzer
function, AF, that is called as (AF HEAD . TAIL) to analyze the form.
See more details about writing analyzer functions below.
- If HEAD satisfies `functionp', which means it is a function in the
running Emacs session, analyze the form as a function call.
- If HEAD is a safe macro (see `elisp-scope-safe-macro-p'), expand it
and analyze the resulting form.
- If HEAD is unknown, then the arguments in TAIL are ignored, unless
`elisp-scope-assume-func' is non-nil, in which case they are analyzed
as evaluated forms (i.e. HEAD is assumed to be a function).
An analyzer (function specified via the `elisp-scope-analyzer' property)
can use the functions `elisp-scope-report-s', `elisp-scope-1' and
`elisp-scope-n' to analyze its arguments, and it can consult the
variable `elisp-scope-output-spec' to obtain the expected output spec of
the analyzed form. For example, the following is a suitable analyzer
for the `identity' function:
(lambda (fsym arg)
(elisp-scope-report-s fsym \\='function)
(elisp-scope-1 arg elisp-scope-output-spec))"
(let* ((stream (or stream (current-buffer)))
(form (read-positioning-symbols stream))
(elisp-scope--counter 0)
(elisp-scope--callback callback)
(max-lisp-eval-depth 32768))
(if (eq stream (current-buffer))
;; `save-excursion' so CALLBACK can change point freely.
(save-excursion (elisp-scope-1 form))
(elisp-scope-1 form))))