THE META-HTML LANGUAGE REFERENCE MANUAL

Language Operators [TOC] Database Commands

Section Intro: Macro Commands

Macro Commands

Synopsis:

    Meta-HTML contains a powerful macro facility, which allows you to define your own commands. Such commands are first-class objects in Meta-HTML; they may even supersede the compiled in definitions.

    There are two types of macros that you can define. One type is a complex-tag; it consists of an opening tag, a body, and a closing tag. The other type is a simple-tag; it only has an opening tag.

    You create a macro by using one of the macro-defining commands. In the body of the definition, special keywords can be placed, which affect what is produced when the macro is invoked. As a macro writer, you have logical access to the arguments passed to the macro in the opening tag, and for complex-tags, you have access to the body which appears between the opening and closing tags.

Commands:

More Information:

    In the opening tag of the macro defining command, several special meta-arguments may be used to affect the binding method used at invocation time to bind the passed parameters to the formal arguments.

    • &optional
      Indicates that the following named parameter is optional, and does not have to be supplied. While at this time Meta-HTML does not complain if there are missing arguments at invocation time, it is likely that the byte-compiler will require function calls to match the formal parameters of the defined function.

      <defun func x &optional y> <get-var x>, <get-var y> </defun>

    • &key
      Indicates that the following named parameters will be bound by the caller placing the name of the parameter followed by an equals sign, and the value of that parameter in the opening tag of the function call. Thus, keyword arguments may appear in any order in the calling function. Here is an example of defining a tag called <image> which will add the width and hieght if they are not already present:

      <defun image &key src width height>
        <if <or <not <get-var width>>
      	  <not <get-var height>>>
            <find-image-xy <get-var src> width height>>
        <img src="<get-var src>" width=<get-var width> height=<get-var height>>
      </defun>

    • &rest
      Gobbles up any remaining arguments to the function, collecting them in the named parameter which follows the &rest. The arguments may be gathered into a single string, or into an array, with one argument per slot. This is controlled by writing the formal parameter name either with or without sqaure braces: (i.e., foo[] or foo).

      <defun func req-arg &rest rest-args[]>
        <ol>
          <foreach x rest-args>
            <li> <get-var x> </li>
          </foreach>
        </ol>
      </defun>

    • &body
      Causes the following named parameter to be bound to the body of the invoked function or macro. For <defun> and <defsubst>, this is all of the material which appeared in the opening tag, while for <defmacro> and <defweakmacro>, this is all of the material that appeared between the opening and closing tags.

      <defmacro with-debugging-output &body body>
        <with-open-stream debug-stream /tmp/debug-output mode=append>
          <stream-put debug-stream <get-var body>>
        </with-open-stream>
      </defmacro>

    • &unevalled
      Modifies the binding rule of a formal parameter such that the material which is bound is not evaluated before the binding takes place. This is almost equivalent to using the %0 ... %9, or %body textual substitutions, but the arguments are bound to variables instead of pure textual substitution. Here is how one might write a function which takes an expression, and produces the expression and the evaluation of the expression as output:

      <defun debug-expr &body &unevalled qbody &body body>
        <get-var-once qbody> EVALS TO: <get-var-once body>
      </defun>

      Such an invocation might look like:

        <set-var x=4 y=5>
        <debug-expr <add x y>>

      which would produce:

        <add x y> EVALS TO: 9

    Here is a ridiculous function, which uses all of the special meta-parameters:

    <defsubst func req &optional opt &key k1 &unevalled k2 &body b &rest args[]>
       REQ: <get-var-once req>,
       OPT: <get-var-once opt>
        K1: <get-var-once k1>
        K2: <get-var-once k2>
      BODY: <get-var-once b>
      REST: <foreach arg args><get-var-once arg> </foreach>
    </defsubst>

    And, here are examples of calling that function:

    Example 1:

    <set-var key-1-arg=key-1>
    <func required k2="Unevalled" opt-arg k1=<get-var key-1-arg> rest0 rest1>
       REQ: required,
       OPT: opt-arg
        K1: key-1
        K2: Unevalled
      BODY: required k2="Unevalled" opt-arg k1=key-1 rest0 rest1
      REST: rest0 rest1
    Example 2:
    <func k2=<get-var k1> required rest0 rest1>
       REQ: required,
       OPT: rest0
        K1: 
        K2: <get-var k1>
      BODY: k2= required rest0 rest1
      REST: rest1

    Notice how in the second example, our optional parameter opt got bound to the second non-keyword argument rest0!

<define-container NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</define-container>
Complex

    Define NAME as a complex tag. At invocation time, various substitutions are made within BODY. Specifically, if the text string is:

    • %0,%1, and so on, upto %9 are replaced with the exact text of the positional arguments that were found in the opening tag of the invocation

    • %attributes is replaced by all of the arguments which appeared in the opening tag.

    • %body is replaced with the exact text of the material that appeared between the opening and closing tags

    • %qbody is similar to %body, but the string is first surrounded by double quotes, and double quote characters which appear in the string are escaped.

    • %xbody is replaced with the evaluation of the material that appeared between the opening and closing tags

    If any NAMED-PARAMETERs are supplied, the values that were passed in the opening tag are evaluated and bound to the named parameters.

    A keyword argument of PACKAGE-NAME wraps the entire body of the macro in an in-package statement.

    The keyword argument WHITESPACE can be set to the string delete to remove whitespace from the starts and ends of lines in the macro definition before it is stored. This effectively concatenates all of the lines of the macro definition into a single long line.

<define-function NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</define-function>
Complex

    Define NAME as a simple tag.

    The only differences between define-function and define-tag are:

    1. The whitespace=delete option is assumed.
    2. The NAMED-PARAMETERs are evaluated in the context of the caller, not of the definition of the defun.
    3. By default, a local package is wrapped around the invocation of the defined function. This can be changed by the use of the PACKAGE=PACKNAME keyword.

    <define-function factorial num>
       <if <lt num 2> 1
          <mul num <factorial <sub num 1>>>>
    </define-function>
    
    <factorial 5> ==> 120

<define-tag NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</define-tag>
Complex

    Define NAME as a simple tag. Within BODY, the values of %0...%9 are defined to be the positional arguments that were found in the opening tag of the invocation, and %body is all of that material in a single string.

    If any NAMED-PARAMETERs are supplied, the values that were passed in the opening tag are evaluated and bound to the named parameters.

    A keyword argument of PACKAGE-NAME wraps the entire body of the macro in an in-package statement.

    The keyword argument WHITESPACE can be set to the string delete to remove whitespace from the starts and ends of lines in the subst definition before it is stored. This effectively concatenates all of the lines of the subst definition into a single long line.

    Also see define-function and define-container.

<defined? NAMESimple

    Returns "true" if NAME is defined as a Meta-HTML primitive or a user-defined function, or the empty string otherwise.

<defmacro NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</defmacro>
Complex

<defsubst NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</defsubst>
Complex

<defun NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</defun>
Complex

<defweakmacro NAME &optional [NAMED-PARAMETERS] &key [PACKAGE=PACKNAME] [WHITESPACE=DELETE]
  body
</defweakmacro>
Complex

    defweakmacro is exactly like define-container, with one exception: at invocation time, the closing tag does not have to be present -- in that case, the invocation is treated as if the definition were a defsubst.

    This facility exists primarily to allow the redefinition of standard HTML constructs which allow the closing tag to be missing, and yet, still inexplicably operate correctly.

    For example, the <p> tag is often used without its closing counterpart of </p>. If you wished to redefine <p> to do something special when a closing tag was found, you might write the following definition:

    <defweakmacro p>
      <verbatim><P></verbatim>
      <when %qbody> Look ma! %body See? </when>
      <verbatim></P></verbatim>
    </defweakmacro>

    then, a simple <P> would produce <P></P>, while a complex invocation, such as:

    <P> this is a list </P>
    produces
      <P> Look ma!  this is a list See? </P>

<primitive? NAMESimple

    Returns "true" if NAME is defined as a Meta-HTML primitive, or the empty string otherwise.

<undef &optional [NAME...]Simple

    Remove the definition of a user-defined defun, defmacro or defsubst. For every NAME that has been defined in this way, the definition is removed.

<user-function? NAMESimple

    Returns "true" if NAME is defined as a user function, or the empty string otherwise.

Edit Section
Function Index
Variable Index


The META-HTML Reference Manual V2.0 Copyright © 1995, 1998, Brian J. Fox
Found a bug? Send mail to bug-manual@metahtml.org