5. Template files

It is possible to use calculus to generate an output file from a template input file, template, using the syntax:

calculus 

[ options… ] input-file… [ -Ttemplate ] [ output-file ]

The template file consists of a list of either template directives or source lines containing escape sequences which are expanded by calculus. Template directive lines are distinguished by having @ as their first character. Escape sequences consist of % following by one or more characters.

There are two template directives; loops take the form:

@loop control
....
@end

and conditionals take the form:

@if condition
....
@else
....
@endif

or:

@if condition
....
@endif

where .... stands for any sequence of template directives or source lines.

The control statements in a loop can be primitive, identity, enum, struct or union to loop over all the primitive, identity, enumeration structure or union types within the input algebra. Within an enum loop it is possible to use enum.const to loop over all the enumeration constants of the current enumeration type. Within a struct loop it is possible to use struct.comp to loop over all the components of the current structure. Within a union loop it is possible to use union.comp to loop over all the shared components of the current union, union.field to loop over all the fields of the current union, and union.map to loop over all the maps of the current union. Within a union.field loop it is possible to use union.field.comp to loop over all the components of the current union field. Within a union.map loop it is possible to use union.map.arg to loop over all the arguments of the current union map.

The valid condition statements in a conditional are true and false, plus comp.complex, which is true if the current structure or union field component has a complex type (i.e. those for which COPY_type and DEREF_type require two arguments), and comp.default, which is true if the current structure or union field component has a default initialiser value.

A number of escape sequences can be used anywhere. %ZX and %ZV give the name and version number of the version of calculus used. %Z and %V give the name and version number of the input algebra. %% and %@ give % and @ respectively, and % as the last character in a line suppresses the following newline character.

Within a primitive loop, %PN gives the primitive name, %PM gives the short primitive name and %PD gives the primitive definition.

Within an identity loop, %IN gives the identity name, %IM gives the short identity name and %IT gives the identity definition.

Within an enum loop, %EN gives the enumeration name, %EM gives the short enumeration name and %EO gives the enumeration order, ORDER_enum. Within an enum.const loop, %ES gives the enumeration constant name and %EV gives its value.

Within a struct loop, %SN gives the structure name and %SM gives the short structure name.

Within a union loop, %UN gives the union name, %UM gives the short union name and %UO gives the union order, ORDER_union. Within a union.field loop, %FN gives the field name. Within a struct.comp, union.comp or union.field.comp loop, %CN gives the component name, %CT gives the component type, %CU gives the short form of the component type and %CV gives the default component initialiser value (if comp.default is true). Within a union.map loop, %MN gives the map name and %MR gives the map return type. Within a union.map.arg loop, %AN gives the argument name and %AT gives the argument type.

As an example, the following template file gives a simple algebra pretty printer:

ALGEBRA %X (%V):

/* PRIMITIVE TYPES */
@loop primitive
%PN (%PM) = "%PD";
@end

/* IDENTITY TYPES */
@loop identity
%IN (%IM) = %IT;
@end

/* ENUMERATION TYPES */
@loop enum

enum %EN (%EM) = {
@loop enum.const
        %ES = %EV,
@end
};
@end

/* STRUCTURE TYPES */
@loop struct

struct %SN (%SM) = {
@loop struct.comp
        %CT %CN;
@end
};
@end

/* UNION TYPES */
@loop union

union %UN (%UM) = {
@loop union.comp
        %CT %CN;
@end
} + {
@loop union.field
        %FN->{
@loop union.field.comp
                %CT %CN;
@end
        };
@end
};
@end