Mymac is a public domain macro preprocessor written in GNU Emacs Lisp. Mymac is different from most preprocessors in that it has an odd lisp-like sytnax. Another important difference is Mymac's ability to bind arbitrary Emacs Lisp expressions to macros. This makes it fairly easy to create macros with powerful effects.
This distribution should be considered an alpha release. It should work with either GNU Emacs 18 or 19, however it hasn't been tested with version 18 recently. This README file is also available in HTML format on the World Wide Web as:
http://www.csclub.uwaterloo.ca/~rridge/mymac.html
Please send any bug reports, questions or comments about mymac to rridge@csclub.uwaterloo.ca
.
Mymac is composed of four files, three Emacs Lisp source files and a mymac input file that defines a standard set of macros. These are:
mymac.el
mymac-fn.el
mymac-ed.el
mymacdef.mm
mymac.el
and mymac-fn.el
define the Emacs Lisp functions and variables that make up mymac. A major mode for editting mymac input files is defined in the third file mymac-ed
. The last file, mymacdef.mm
is read by mymac when mymac-fn.el
is loaded (or byte compiled) and provides a hopefully useful set of predefined macros to
use.
There are two ways macros can be used. The simplest method is to have the macro's name appear separated from the rest of the text by whitespace. This results in the macro being expanded without any arguments. The other method is supply arguments to the macro by surrounding the macro name, followed by the arguments, with braces. The macro name must appear immediately after the left-brace ({) without any space between them. The arguments should be separated by whitespace. For example:
1 {define SAMPLE-MACRO test} 2 SAMPLE-MACROThe first line results in the macro
define
being expanded with two arguments SAMPLE-MACRO
and test
. The standard macro define (see below) expands to
nothing, but as side effect it creates a new macro definition. The first
argument to define is the name of the new macro, the rest of the
arguments are catenated together and form the definition of macro. On
the second line, the macro SAMPLE-MACRO
, defined on the
previous line, is used, and will be expanded as the string test
.
Mymac aggressively expands macros. Both the arguments of a macro and the result of a macro are subject to macro expansion. This can lead to surprising results. For example:
1 {define SAMPLE-MACRO test} 2 {define SAMPLE-MACRO banana} 3 test 4 SAMPLE-MACROis expanded as:
1 2 3 banana 4 bananaLine one is straight forward, it defines the macro
SAMPLE-MACRO
with the string test
. The first
surprise in this example is on line two. Instead of redefining the macro SAMPLE-MACRO
it defines a macro called test
. This
is because the arguments to the macro define are expanded before being
applied to the macro. This results in the argument SAMPLE-MACRO
being expanded as test
and so a macro
named test
is defined as the string banana. Knowing
this, line three isn't much of a surprise, test
is a
macro which gets expanded as banana
. Line four is the
other surprise, if SAMPLE-MACRO
wasn't redefined as banana
why was it expanded as banana
anyways? The reason is because the result of macro expansion is
itself subject macro expansion. SAMPLE-MACRO
is
expanded as test
which is further expanded as banana
.
You can create a macro that takes argument by placing sequences of
the form ${1}
in the definition. The number within the
braces is the index of the argument to substitute in it's place when
the macro is expanded. For example:
1 {define SAMPLE-MACRO get ${1} her } 2 {SAMPLE-MACRO to}expands as:
1 2 together
To prevent text from being expanded you can quote it by surrounding the text with backquotes ('). Within backquotes you can use backslash characters (\) to "escape" backquotes and backslashes. Backquoted text in the input file is processed by removing the backquotes surrounding it as well as one level of backslash characters. Mymac also aggressively removes backquotes. Backquote removal also happens after macros are expanded and in macro arguments. Backquoted text in macro arguments is considered one argument. For example:
1 {define `SAMPLE-MACRO` test} 2 `SAMPLE-MACRO` 3 {define `banana` apple} 4 {define `SAMPLE-MACRO` banana} 5 {define `banana` peach} 6 SAMPLE-MACRO 7 {define `SAMPLE-MACRO` `banana`} 8 {define `banana` orange} 9 SAMPLE-MACRO 10 {define `SAMPLE-MACRO` `\`banana\``} 11 SAMPLE-MACRO 12 {define `SAMPLE-MACRO` `\`\\\`banana\\\`\``} 13 SAMPLE-MACROexpands as:
1 2 SAMPLE-MACRO 3 4 5 6 apple 7 8 9 orange 10 11 banana 12 13 `banana`
Mymac macros are represented interally as Emacs Lisp symbols. This means, like Emacs Lisp symbols, macros have two values: an ordinary value and a function value. Unlike Emacs Lisp symbols, where the value used depends on the context where the symbol is used during evalation, both values are used when a macro is expanded. The function value of a macro is a lambda expression that takes at least one argument. When the macro is expanded this function is called and the result, a string, is used as the expansion. The first argument the function is passed is the value part of macro. The arguments of the macro, if any, are passed as strings as the rest of the arguments to the function.
There is only one macro that's fundamental to mymac, bind-lisp-expr
, all other macros are either defined with this
macro or with other macros.
bind-lisp-expr
is used to bind Emacs Lisp
expressions to macros. The first argument of the macro is name of a macro
to create or rebind. The second argument is an Emacs Lisp expression. This
expression is immediately evaluated and the result is bound to the
macro as its function value. If the result isn't a lambda expression
it is made into one by prepending (lambda (value &rest args) ...)
to it. Optionally two more arguments can appear. The third
argument gives the name of a uninterned symbol to byte compile the
lambda expression with. The function value of the macro is then set
to this symbol. The forth argument, if supplied will enable
optimization when lambda expression is compiled. This macro always
expands to an empty string.
The file mymacdef.mm defines the following standard macros:
Mymac add the following commands to Emacs:
mymac-expand-buffer
this command expands
all the macros in the current buffer, but instead of placing the output
in a different buffer, the output is replaces the contents of the current
buffer.
mymac-batch-expand-file
is available for use in batch
mode. It takes it's arguments from the command line.
mymac-expand-buffer
and C-c ` is bound to the command mymac-toggle-syntax
.
bind-lisp-expr
.
Mymac 1.0 README file / Ross Ridge / rridge@csclub.uwaterloo.ca