X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/37680279159b37e6bcb20039988aff6a26204ad4..37aa90e5196e7af28b2f0dd429a348d222c006f4:/lispref/macros.texi diff --git a/lispref/macros.texi b/lispref/macros.texi index 301dc124f3..0a1bf942c2 100644 --- a/lispref/macros.texi +++ b/lispref/macros.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Emacs Lisp Reference Manual. -@c Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1998 Free Software Foundation, Inc. +@c Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1998, 2004 Free Software Foundation, Inc. @c See the file elisp.texi for copying conditions. @setfilename ../info/macros @node Macros, Customization, Functions, Top @@ -30,6 +30,7 @@ instead. @xref{Inline Functions}. * Backquote:: Easier construction of list structure. * Problems with Macros:: Don't evaluate the macro arguments too many times. Don't hide the user's variables. +* Indenting Macros:: Specifying how to indent macro calls. @end menu @node Simple Macro @@ -136,6 +137,25 @@ uses this feature. @end smallexample @end defun + +@defun macroexpand-all form &optional environment +@cindex macro expansion in entire form +@code{macroexpand-all} expands macros like @code{macroexpand}, but +will look for and expand all macros in @var{form}, not just at the +top-level. If no macros are expanded, the return value is @code{eq} +to @var{form}. + +Repeating the example used for @code{macroexpand} above with +@code{macroexpand-all}, we see that @code{macroexpand-all} @emph{does} +expand the embedded calls to @code{inc}: + +@smallexample +(macroexpand-all '(inc2 r s)) + @result{} (progn (setq r (1+ r)) (setq s (1+ s))) +@end smallexample + +@end defun + @node Compiling Macros @section Macros and Byte Compilation @cindex byte-compiling macros @@ -205,6 +225,41 @@ any @code{interactive} declaration is ignored since macros cannot be called interactively. @end defspec + The body of the macro definition can include a @code{declare} form, +which can specify how @key{TAB} should indent macro calls, and how to +step through them for Edebug. + +@defmac declare @var{specs}@dots{} +@anchor{Definition of declare} +A @code{declare} form is used in a macro definition to specify various +additional information about it. Two kinds of specification are +currently supported: + +@table @code +@item (debug @var{edebug-form-spec}) +Specify how to step through macro calls for Edebug. +@xref{Instrumenting Macro Calls}, for more details. + +@item (indent @var{indent-spec}) +Specify how to indent calls to this macro. @xref{Indenting Macros}, +for more details. +@end table + +A @code{declare} form only has its special effect in the body of a +@code{defmacro} form if it immediately follows the documentation +string, if present, or the argument list otherwise. (Strictly +speaking, @emph{several} @code{declare} forms can follow the +documentation string or argument list, but since a @code{declare} form +can have several @var{specs}, they can always be combined into a +single form.) When used at other places in a @code{defmacro} form, or +outside a @code{defmacro} form, @code{declare} just returns @code{nil} +without evaluating any @var{specs}. +@end defmac + + No macro absolutely needs a @code{declare} form, because that form +has no effect on how the macro expands, on what the macro means in the +program. It only affects secondary features: indentation and Edebug. + @node Backquote @section Backquote @cindex backquote (list substitution) @@ -320,6 +375,7 @@ This section describes some important consequences that can lead to trouble, and rules to follow to avoid trouble. @menu +* Wrong Time:: Do the work in the expansion, not in the macro. * Argument Evaluation:: The expansion should evaluate each macro arg once. * Surprising Local Vars:: Local variable bindings in the expansion require special care. @@ -327,6 +383,37 @@ trouble, and rules to follow to avoid trouble. * Repeated Expansion:: Avoid depending on how many times expansion is done. @end menu +@node Wrong Time +@subsection Wrong Time + + The most common problem in writing macros is doing some of the +real work prematurely---while expanding the macro, rather than in the +expansion itself. For instance, one real package had this macro +definition: + +@example +(defmacro my-set-buffer-multibyte (arg) + (if (fboundp 'set-buffer-multibyte) + (set-buffer-multibyte arg))) +@end example + +With this erroneous macro definition, the program worked fine when +interpreted but failed when compiled. This macro definition called +@code{set-buffer-multibyte} during compilation, which was wrong, and +then did nothing when the compiled package was run. The definition +that the programmer really wanted was this: + +@example +(defmacro my-set-buffer-multibyte (arg) + (if (fboundp 'set-buffer-multibyte) + `(set-buffer-multibyte ,arg))) +@end example + +@noindent +This macro expands, if appropriate, into a call to +@code{set-buffer-multibyte} that will be executed when the compiled +program is actually run. + @node Argument Evaluation @subsection Evaluating Macro Arguments Repeatedly @@ -358,7 +445,7 @@ For example, (for i from 1 to 10 do (print i))." (let ((i 1)) (while (<= i 3) (setq square (* i i)) - (princ (format "%d %d" i square)) + (princ (format "\n%d %d" i square)) (inc i))) @end group @group @@ -414,7 +501,7 @@ macro. Here is a correct expansion for the @code{for} macro: @end group @end smallexample -Here is a macro definition that creates this expansion: +Here is a macro definition that creates this expansion: @smallexample @group @@ -604,3 +691,62 @@ One way to avoid pathological cases like this is to think of allocation construct. You wouldn't use @code{setcar} on a constant such as @code{'(nil)}, so naturally you won't use it on @code{(empty-object)} either. + +@node Indenting Macros +@section Indenting Macros + + You can use the @code{declare} form in the macro definition to +specify how to @key{TAB} should indent indent calls to the macro. You +write it like this: + +@example +(declare (indent @var{indent-spec})) +@end example + +@noindent +Here are the possibilities for @var{indent-spec}: + +@table @asis +@item @code{nil} +This is the same as no property---use the standard indentation pattern. +@item @code{defun} +Handle this function like a @samp{def} construct: treat the second +line as the start of a @dfn{body}. +@item an integer, @var{number} +The first @var{number} arguments of the function are +@dfn{distinguished} arguments; the rest are considered the body +of the expression. A line in the expression is indented according to +whether the first argument on it is distinguished or not. If the +argument is part of the body, the line is indented @code{lisp-body-indent} +more columns than the open-parenthesis starting the containing +expression. If the argument is distinguished and is either the first +or second argument, it is indented @emph{twice} that many extra columns. +If the argument is distinguished and not the first or second argument, +the line uses the standard pattern. +@item a symbol, @var{symbol} +@var{symbol} should be a function name; that function is called to +calculate the indentation of a line within this expression. The +function receives two arguments: +@table @asis +@item @var{state} +The value returned by @code{parse-partial-sexp} (a Lisp primitive for +indentation and nesting computation) when it parses up to the +beginning of this line. +@item @var{pos} +The position at which the line being indented begins. +@end table +@noindent +It should return either a number, which is the number of columns of +indentation for that line, or a list whose car is such a number. The +difference between returning a number and returning a list is that a +number says that all following lines at the same nesting level should +be indented just like this one; a list says that following lines might +call for different indentations. This makes a difference when the +indentation is being computed by @kbd{C-M-q}; if the value is a +number, @kbd{C-M-q} need not recalculate indentation for the following +lines until the end of the list. +@end table + +@ignore + arch-tag: d4cce66d-1047-45c3-bfde-db6719d6e82b +@end ignore