Mymac 1.0 README file

By Ross Ridge
Public Domain

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.

Contents

Installing Mymac

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:

These files should be installed somewhere in your Emacs load path. The first two files, 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.

Using Macros

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-MACRO
The 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-MACRO
is expanded as:
	1 
	2 
	3 banana
	4 banana
Line 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

Quoting

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-MACRO
expands as:
	 1 
	 2 SAMPLE-MACRO
	 3 
	 4 
	 5 
	 6 apple
	 7 
	 8 
	 9 orange
	10 
	11 banana
	12 
	13 `banana`

Standard Macros

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 macro-name lisp-expression [ symbol-name [ optimize ]] }
The macro 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:

{define macro-name [args ...]}
The define macro creates simple macros. The first argument is the name of the macro to create or redefine. The remaining arguments are catenated together to form the definition of the macro. This macro always expands to an empty string.
{undef macro-name}
The undef macro undefines macros. The first argument is name of the macro that will no longer be expanded. This macro always expands to an empty string.
{ignore [args ...]}
The ignore macro simply ignores it's arguments. The arguments are still expanded as usual. This macro is handy for wrapping around other macros so you can format them however you want without having a large amount of unecessary space appearing in the output. This macro always expands to an empty string.
{include file-name}
The include macro includes another file into the input. The first argument is the name of the file to include. This macro expands to the contents of the included file.
{foreach macro-name separator [args ...]}
The foreach macro repeatedly expands a macro. The first argument is the name of a macro. The second argument is a separator to use in the expansion of the macro. For each of the remaining arguments the supplied macro is expanded with that argument as a parameter. These expansions are joined together using the separator and the result is the final expansion of this macro.
{quote [args ...]}
Surrounds the the catenated list of arguments with backquotes (`) and puts a backslash (\) before any backslash or backquote characters in the quoted text. This macro is usually used to join several macro arguments into a single macro argument.

Commands

Mymac add the following commands to Emacs:

mymac-expand-buffer
Processes the current buffers as mymac input and expands all the macros in it. The expanded output is placed in a newly created buffer and this buffer is made the current buffer.
mymac-expand-buffer-in-place
Like 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-expand-file
This command prompts for two arguments, a source file and a destination file. The source file is read in, expanded and then result is written to the destination file. A version of this command mymac-batch-expand-file is available for use in batch mode. It takes it's arguments from the command line.
mymac-edit-mode
A major mode for editting mymac input files. C-c C-e is bound the to command mymac-expand-buffer and C-c ` is bound to the command mymac-toggle-syntax.
macro-toggle-syntax
Toggles between the two syntax tables used in Mymac Edit mode. One is the syntax table used by mymac itself, this the syntax table used initially when Mymac Edit mode is entered. The other syntax table is the table used in the major mode for editting Emacs Lisp source. This command allows the user to switch between editting normal mymac input files and the Emacs Lisp expressions used with the macro bind-lisp-expr.
mymac-dump-macros
Dumps a list of the mymac macros currently defined, with their definitions, to a buffer.

Mymac 1.0 README file / Ross Ridge / rridge@csclub.uwaterloo.ca