Reference Developer Tutorial 1 Introduction 2 Macros 3 Typesetting 4 Example 5 Hints 6 Examples 7 Webmaking SEARCH

2.4 Additive Macros

Sometimes it is convenient to build up the definition of a macro in stages throughout the input file. In FunnelWeb, this can be done using an additive macro. An additive macro is identical to an ordinary macro except that

1. It has `+=` instead of `==`.
2. It can be defined in one or more parts throughout the input file. The definition of the macro is the concatenation of all the parts in the order in which they appear.

The following example shows how additive macros can be used to scatter and regroup information, in this case assisting in the lucid construction of a data abstraction in a language (Pascal) that does not support them explicitly.

    @!******************************

    @O@<prog.pas@>==@{@-
    program adt(input,output);
    @<Types@>
    @<Variables@>
    @<Procedures@>
    begin startproc; end.
    @}

    @!******************************

    @$@<Types@>+=@{@-
    type buffer_type =
       record
       length : integer;
       buf : array[1..100] of char;
       end;
    @}

    @$@<Variables@>+=@{@-
    bigbuf : buffer_type;
    @}

    @$@<Procedures@>+=@{@-
    procedure buf_init (var b : buffer_type               )
       {Body of buf_init}
    procedure buf_add  (var b : buffer_type;     ch : char)
       {Body of buf_add}
    procedure buf_get  (var b : buffer_type; var ch : char)
       {Body of buf_get}
    @}

    @!******************************

    @$@<Types@>+=@{@-
    type complex_type = record r,i : real; end;
    @}

    @$@<Procedures@>+=@{@-
    procedure cm_set (var c: complex_type; a,b: real)
       {Body of cm_set}
    procedure cm_add (a,b: complex_type; var c: complex_type)
       {Body of cm_add}
    {Other procedures and functions}
    @}

    @!******************************

    {...more pieces of program...}

    @!******************************

It is important to remember that the definition of each macro does not change throughout the input file. FunnelWeb parses the entire input file and assembles all the macro definitions before it even starts to expand macros. As a result, each additive macro can only have one definition, and that definition is the concatenation of all its parts.

The example above shows how additive macros can be used to rearrange the presentation of a computer program in the order in which the user wishes to discuss it rather than the order in which the compiler requires that it be consumed. It is easy, however, to abuse the feature of additive macros. In many cases, the same effect can be obtained more clearly by replacing each part of an additive macro in-situ using uniquely named non-additive macros, and then collect them together as a group at the point where the additive macro is called. Doing this is more work, and is more error prone, but can result in a clearer exposition. The following program illustrates this alternative approach.

    @!******************************

    @O@<prog.pas@>==@{@-
    program adt(input,output);
    @<Types@>
    @<Variables@>
    @<Procedures@>
    begin startproc; end.
    @}

    @$@<Types@>==@{@-
    @<Buffer type@>
    @<Complex type@>
    @}

    @$@<Variables@>==@{@-
    @<Buffer variable@>
    @}

    @$@<Procedures@>==@{@-
    @<Buffer procedures@>
    @<Complex procedures@>
    @}

    @!******************************

    @$@<Buffer type@>==@{@-
    type buffer_type = record
                       length : integer;
                       buf : array[1..100] of char;
                       end;
    @}

    @$@<Buffer variable@>==@{@-
    bigbuf : buffer_type;
    @}

    @$@<Buffer procedures@>==@{@-
    procedure buf_init(var b : buffer_type)
       {Body of buf_init}
    procedure buf_add(var b : buffer_type; ch : char)
       {Body of buf_add}
    procedure buf_get(var b : buffer_type; var ch : char)
       {Body of buf_get}
    @}

    @!******************************

    @$@<Complex type@>==@{@-
    type complex_type = record r,i : real; end;
    @}

    @$@<Complex procedures@>+=@{@-
    procedure cm_set(var c: complex_type; a,b : real)
       {Body of cm_set}
    procedure cm_add(a,b : complex_type; var c: complex_type)
       {Body of cm_add}
    {Other procedures and functions}
    @}

    @!******************************

    {...more pieces of program...}

    @!******************************

One of advantages of FunnelWeb (and literate programming in general) is that (as shown above) it allows the user to lay out the program in whatever order is desired with near total independence from the ordering requirements of the target programming language.

Additive macros are allowed to be tagged with `@Z` and `@M` just as other macros can, but the tags must appear only on the first definition of the macro. Additive macros cannot be connected directly to product files.

Webmaster Copyright © Ross N. Williams 1992,1999. All rights reserved.