Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
<!-- Crown Copyright (c) 1998 -->
2
<HTML>
3
<HEAD>
4
<TITLE>
5
calculus users' guide 
6
</TITLE>
7
</HEAD>
8
 
9
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#400080" ALINK="#FF0000">
10
<H1>calculus Users' Guide</H1>
11
<H3>January 1998</H3>
12
<IMG SRC="../images/no_next.gif" ALT="next section">
13
<IMG SRC="../images/no_prev.gif" ALT="previous section">
14
<IMG SRC="../images/no_top.gif" ALT="current document">
15
<A HREF="../index.html"><IMG SRC="../images/home.gif" ALT="TenDRA home page">
16
</A>
17
<IMG SRC="../images/no_index.gif" ALT="document index"><P>
18
<HR>
19
<DL>
20
<DT><A HREF="#Intro"><B>1</B> - Introduction</A><DD>
21
<DL>
22
<DT><A HREF="#Options"><B>1.1</B> - Using calculus</A><DD>
23
<DT><A HREF="#Example"><B>1.2</B> - Example program</A><DD>
24
</DL>
25
<DT><A HREF="#TextInput"><B>2</B> - Input syntax</A><DD>
26
<DL>
27
<DT><A HREF="#InputPrim"><B>2.1</B> - Primitives</A><DD>
28
<DT><A HREF="#InputIdent"><B>2.2</B> - Identities</A><DD>
29
<DT><A HREF="#InputEnum"><B>2.3</B> - Enumerations</A><DD>
30
<DT><A HREF="#InputStruct"><B>2.4</B> - Structures</A><DD>
31
<DT><A HREF="#InputUnion"><B>2.5</B> - Unions</A><DD>
32
<DT><A HREF="#InputType"><B>2.6</B> - Type constructors</A><DD>
33
<DT><A HREF="#Module"><B>2.7</B> - Relations between algebras</A><DD>
34
</DL>
35
<DT><A HREF="#TokenOutput"><B>3</B> - Output type system specification</A><DD>
36
<DL>
37
<DT><A HREF="#OutputInfo"><B>3.1</B> - Version information</A><DD>
38
<DT><A HREF="#OutputBasic"><B>3.2</B> - Basic types</A><DD>
39
<DT><A HREF="#OutputSize"><B>3.3</B> - Operations on sizes</A><DD>
40
<DT><A HREF="#OutputPtr"><B>3.4</B> - Operations on pointers</A><DD>
41
<DT><A HREF="#OutputList"><B>3.5</B> - Operations on lists</A><DD>
42
<DT><A HREF="#OutputStack"><B>3.6</B> - Operations on stacks</A><DD>
43
<DT><A HREF="#OutputVec"><B>3.7</B> - Operations on vectors</A><DD>
44
<DT><A HREF="#OutputVecPtr"><B>3.8</B> - Operations on vector pointers</A><DD>
45
<DT><A HREF="#OutputPrim"><B>3.9</B> - Operations on primitives</A><DD>
46
<DT><A HREF="#OutputIdent"><B>3.10</B> - Operations on identities</A><DD>
47
<DT><A HREF="#OutputEnum"><B>3.11</B> - Operations on enumerations</A><DD>
48
<DT><A HREF="#OutputStruct"><B>3.12</B> - Operations on structures</A><DD>
49
<DT><A HREF="#OutputUnion"><B>3.13</B> - Operations on unions</A><DD>
50
</DL>
51
<DT><A HREF="#COutput"><B>4</B> - Implementation details</A><DD>
52
<DL>
53
<DT><A HREF="#COutputTypes"><B>4.1</B> - Implementation of types</A><DD>
54
<DT><A HREF="#COutputSupport"><B>4.2</B> - Support routines</A><DD>
55
<DT><A HREF="#COutputAssert"><B>4.3</B> - Run-time checking</A><DD>
56
</DL>
57
<DT><A HREF="#DiskOutput"><B>5</B> - Disk reading and writing</A><DD>
58
<DL>
59
<DT><A HREF="#DiskWrite"><B>5.1</B> - Disk writing routines</A><DD>
60
<DT><A HREF="#DiskRead"><B>5.2</B> - Disk reading routines</A><DD>
61
<DT><A HREF="#DiskPrint"><B>5.3</B> - Object printing routines</A><DD>
62
<DT><A HREF="#DiskAlias"><B>5.4</B> - Aliasing</A><DD>
63
<DT><A HREF="#Application"><B>5.5</B> - Application to calculus</A><DD>
64
</DL>
65
<DT><A HREF="#Templates"><B>6</B> - Template files</A><DD>
66
</DL>
67
 
68
<HR>
69
<H2><A NAME="Intro">1. Introduction</A></H2>
70
<P>
71
This document describes a tool, <CODE>calculus</CODE>, which allows
72
complex type systems to be described in a simple algebraic format,
73
and transforms this into a system of C types which implements this
74
algebra. 
75
</P>
76
<P>
77
<CODE>calculus</CODE> was initially written as a design tool for use
78
with the TenDRA C and C++ producers.  The producers' internal datatypes
79
reflect the highly complex interdependencies between the C and C++
80
language concepts (types, expressions and so on) which they were designed
81
to represent.  A tool for managing this complexity and allowing changes
82
to the internal datatypes to be made with confidence was therefore
83
seen to be an absolute necessity.  The tool can also be applied in
84
similar situations where a complex type system needs to be described.
85
</P>
86
<P>
87
The tool also provides for a separation between the specification
88
of the type system and its implementation in terms of actual C types.
89
This separation has a number of advantages.  The advantages of maintaining
90
a level of abstraction in the specification are obvious.  It is possible
91
to apply extremely rigorous type checking to any program written using
92
the tool, thereby allowing many potential errors to be detected at
93
compile time.  It is also possible to restrict access to the types
94
to certain well-specified constructs, thereby increasing the maintainability
95
of code written using the tool. 
96
</P>
97
<P>
98
This separation also has beneficial effects on the implementation
99
of the type system.  By leaving all the type checking aspects at the
100
specification level, it is possible to impose an extremely homogeneous
101
underlying implementation.  This means, for example, that a single
102
memory management system can be applied to all the types within the
103
system.  It also opens the possibility of writing operations which
104
apply to all types within the system in a straightforward manner.
105
The <A HREF="#DiskOutput">disk reading and writing routines</A> described
106
below are an example of this. 
107
</P>
108
 
109
<H3><A NAME="Options">1.1. Using calculus</A></H3>
110
<P>
111
The general form for invoking <CODE>calculus</CODE> is as follows:
112
<PRE>
113
	calculus [ <I>options</I> ] <I>input</I> .... [ <I>output</I> ]
114
</PRE>
115
where <I>input</I> is a file containing the input type system description
116
and <I>output</I> is the directory where the files implementing this
117
system are to be output.  This directory must already exist.  If no
118
<I>output</I>
119
argument is given then the current working directory is assumed. 
120
Note that several <I>input</I> files can be given.  Unless 
121
<A HREF="#Module">otherwise specified</A> it is the last file which
122
is used to generate the output. 
123
</P>
124
<P>
125
The form in which the <A HREF="#TextInput">input type systems</A>
126
are expressed is described below.  The form of the output depends
127
on 
128
<I>options</I>.  By default, the C implementation of the type system
129
is output.  If the <CODE>-t</CODE> option is passed to <CODE>calculus</CODE>
130
then <A HREF="../tcpplus/token.html"><CODE>#pragma token</CODE></A>
131
statements describing the type system specification are output.  This
132
<A HREF="#TokenOutput">specification</A> is given below, with some
133
of the more important <A HREF="#COutput">implementation details</A>
134
being described in the following section. 
135
</P>
136
<P>
137
Note that it is necessary to check any program written using 
138
<CODE>calculus</CODE> against the <CODE>#pragma token</CODE> version
139
of the specification in order to get the full benefits of the rigorous
140
type checking provided by the tool.  Some sections of the program
141
(if only the 
142
<A HREF="#COutputSupport">basic functions</A>) may be dependent upon
143
the implementation, and so not be suitable for this form of checking.
144
</P>
145
 
146
<H3><A NAME="Example">1.2. Example program</A></H3>
147
<P>
148
The program <CODE>calculus</CODE> itself was written using a type
149
system specified using the <CODE>calculus</CODE> tool.  It is designed
150
to provide an example of its own application, with some features not
151
strictly necessary for the functionality of the program being added
152
for illustrative purposes. 
153
</P>
154
 
155
<HR>
156
<H2><A NAME="TextInput">2. Input syntax</A></H2>
157
<P>
158
The overall input file format is as follows: 
159
<PRE>
160
	<I>algebra</I> :
161
		ALGEBRA <I>identifier version<SUB>opt</SUB></I> : <I>item-list<SUB>opt</SUB>
162
</I>
163
 
164
	<I>version</I> :
165
		( <I>integer</I> . <I>integer</I> )
166
 
167
	<I>item-list</I> :
168
		<I>item</I>
169
		<I>item-list item</I>
170
 
171
	<I>item</I> :
172
		<I>primitive</I>
173
		<I>identity</I>
174
		<I>enumeration</I>
175
		<I>structure</I>
176
		<I>union</I>
177
</PRE>
178
The initial identifier gives the overall name of the algebra.  A version
179
number may also be associated with the algebra (if this is omitted
180
the version is assumed to be 1.0).  The main body of the algebra definition
181
consists of a list of items describing the primitives, the identities,
182
the enumerations, the structures and the unions comprising the algebra.
183
</P>
184
<P>
185
Here <I>identifier</I> has the same meaning as in C.  The only other
186
significant lexical units are <I>integer</I>, which consists of a
187
sequence of decimal digits, and <I>string</I>, which consists of any
188
number of characters enclosed in double quotes.  There are no escape
189
sequences in strings.  C style comments may be used anywhere in the
190
input.  White space is not significant. 
191
</P>
192
 
193
<H3><A NAME="InputPrim">2.1. Primitives</A></H3>
194
<P>
195
Primitives form the basic components from which the other types in
196
the algebra are built up.  They are described as follows: 
197
<PRE>
198
	<I>primitive</I> :
199
		<I>object-identifier</I> = <I>quoted-type</I> ;
200
</PRE>
201
where the primitive identifier is given by: 
202
<PRE>
203
	<I>object-identifier</I> :
204
		#<I><SUB>opt</SUB></I> :<I><SUB>opt</SUB> identifier</I>
205
		#<I><SUB>opt</SUB></I> :<I><SUB>opt</SUB> identifier</I> ( <I>identifier</I> )
206
</PRE>
207
and the primitive definition is a string which gives the C type corresponding
208
to this primitive: 
209
<PRE>
210
	<I>quoted-type</I> :
211
		<I>string</I>
212
</PRE>
213
Note that each primitive (and also each identity, each enumeration,
214
each structure and each union) has two names associated with it. 
215
The second name is optional; if it is not given then it is assumed
216
to be the same as the first name.  The first name is that which will
217
be given to the corresponding type in the output file.  The second
218
is a short form of this name which will be used in forming constructor
219
names etc. in the output. 
220
</P>
221
<P>
222
The optional hash and colon which may be used to qualify an object
223
identifier are provided for backwards compatibility only and are not
224
used in the output routines. 
225
</P>
226
 
227
<H3><A NAME="InputIdent">2.2. Identities</A></H3>
228
<P>
229
Identities are used to associate a name with a particular type in
230
the algebra.  In this they correspond to <CODE>typedef</CODE>s in
231
C.  They are described as follows: 
232
<PRE>
233
	<I>identity</I> :
234
		<I>object-identifier</I> = <I>type</I> ;
235
</PRE>
236
where the definition type, <I>type</I>, is as described 
237
<A HREF="#InputType">below</A>. 
238
</P>
239
 
240
<H3><A NAME="InputEnum">2.3. Enumerations</A></H3>
241
<P>
242
Enumerations are used to define types which can only take values from
243
some finite set.  They are described as follows: 
244
<PRE>
245
	<I>enumeration</I> :
246
		enum !<I><SUB>opt</SUB> object-identifier</I> = { <I>enumerator-list</I> } ;
247
		enum !<I><SUB>opt</SUB> object-identifier</I> = <I>base-enumeration</I> + { 
248
<I>enumerator-list</I> } ;
249
</PRE>
250
where: 
251
<PRE>
252
	<I>base-enumeration</I> :
253
		<I>identifier</I>
254
</PRE>
255
is the name of a previously defined enumeration type.  The latter
256
form is used to express extension enumeration types.  An enumeration
257
type may be qualified by an exclamation mark to indicate that no lists
258
of this type will be constructed. 
259
</P>
260
<P>
261
The enumeration constants themselves are defined as follows: 
262
<PRE>
263
	<I>enumerator</I> :
264
		<I>identifier</I>
265
		<I>identifier</I> = <I>enumerator-value</I>
266
 
267
	<I>enumerator-list</I> :
268
		<I>enumerator</I>
269
		<I>enumerator-list</I> , <I>enumerator</I>
270
</PRE>
271
Each enumerator is assigned a value in an ascending sequence, starting
272
at zero.  The next value to be assigned can be set using an 
273
<I>enumerator-value</I>.  This is an expression formed from 
274
<I>integer</I>s, <I>identifier</I>s representing previous enumerators
275
from the same enumeration, and the question mark character which stands
276
for the previous enumeration value.  The normal C arithmetic operations
277
can be applied to build up more complex <I>enumerator-value</I>s.
278
All enumerator evaluation is done in the <CODE>unsigned long</CODE>
279
type of the host machine.  Values containing more than 32 bits are
280
not portable. 
281
</P>
282
<P>
283
Enumerations thus correspond to enumeration types in C, except that
284
they are genuinely distinct types. 
285
</P>
286
 
287
<H3><A NAME="InputStruct">2.4. Structures</A></H3>
288
<P>
289
Structures are used to build up composite types from other types in
290
the algebra.  They correspond to structures in C.  They are described
291
as follows: 
292
<PRE>
293
	<I>structure</I> :
294
		struct <I>object-identifier</I> = <I>component-group</I> ;
295
		struct <I>object-identifier</I> = <I>base-structure</I> + <I>component-group
296
</I> ;
297
</PRE>
298
where: 
299
<PRE>
300
	<I>base-structure</I> :
301
		<I>identifier</I>
302
</PRE>
303
is the name of a previously defined structure type.  The latter form
304
is used to express (single) inheritance of structures.  All components
305
of the base structure also become components of the derived structure.
306
</P>
307
<P>
308
The structure components themselves are defined as follows: 
309
<PRE>
310
	<I>component-group</I> :
311
		{ <I>component-list<SUB>opt</SUB></I> }
312
 
313
	<I>component-list</I> :
314
		<I>component-declarations</I> ;
315
		<I>component-list component-declarations</I> ;
316
 
317
	<I>component-declarations</I> :
318
		<I>type component-declarators</I>
319
 
320
	<I>component-declarators</I> :
321
		<I>component-declarator</I>
322
		<I>component-declarators</I> , <I>component-declarator</I>
323
 
324
	<I>component-declarator</I> :
325
		<I>identifier component-initialiser<SUB>opt</SUB></I>
326
 
327
	<I>component-initialiser</I> :
328
		= <I>string</I>
329
</PRE>
330
The optional <A HREF="#OutputStruct">component initialiser strings</A>
331
are explained below. 
332
</P>
333
<P>
334
Structures are the only algebra construct which prevent the input
335
from being a general graph.  Unions may be defined in terms of themselves,
336
but (as in C) pointers must be used to define structures in terms
337
of themselves. 
338
</P>
339
 
340
<H3><A NAME="InputUnion">2.5. Unions</A></H3>
341
<P>
342
Unions are used to build up types which can hold a variety of information.
343
They differ from C unions in that they are discriminated.  They are
344
described as follows: 
345
<PRE>
346
	<I>union</I> :
347
		union <I>object-identifier</I> = <I>component-group</I> + <I>field-group map-group
348
<SUB>opt</SUB></I> ;
349
		union <I>object-identifier</I> = <I>base-union</I> + <I>field-group map-group
350
<SUB>opt</SUB></I> ;
351
</PRE>
352
where: 
353
<PRE>
354
	<I>base-union</I> :
355
		<I>identifier</I>
356
</PRE>
357
is the name of a previously defined union type.  The latter form is
358
used to express (single) inheritance of unions.  All components, fields
359
and maps of the base union also become components of the derived union.
360
Note that only new fields and maps can be added in the derived union.
361
</P>
362
<P>
363
The <I>component-group</I> gives a set of components which are common
364
to all the different union cases.  The cases themselves are described
365
as follows: 
366
<PRE>
367
	<I>field-group</I> :
368
		{ <I>field-list</I> }
369
 
370
	<I>field</I> :
371
		#<I><SUB>opt</SUB></I> #<I><SUB>opt</SUB> field-identifier-list</I> -&gt; <I>component-group
372
</I>
373
		#<I><SUB>opt</SUB></I> #<I><SUB>opt</SUB> field-identifier-list</I> -&gt; <I>base-field
374
</I> + <I>component-group</I>
375
 
376
	<I>base-field</I> :
377
		<I>identifier</I>
378
 
379
	<I>field-list</I> :
380
		<I>field</I>
381
		<I>field-list</I> , <I>field</I>
382
 
383
	<I>field-identifier</I> :
384
		<I>identifier</I>
385
 
386
	<I>field-identifier-list</I> :
387
		<I>field-identifier</I>
388
		<I>field-identifier-list</I> , <I>field-identifier</I>
389
</PRE>
390
The optional one or two hashes which may be used to qualify a list
391
of field identifiers are used to indicate <A HREF="#DiskAlias">aliasing</A>
392
in the disk reading and writing routines.  The <I>base-field</I> case
393
is a notational convenience which allows one field in a union to inherit
394
all the components of another field. 
395
</P>
396
<P>
397
Note that a number of field identifiers may be associated with the
398
same set of field components.  Any such list containing more than
399
one identifier forms a field identifier set, named after the first
400
field identifier. 
401
</P>
402
<P>
403
In addition a number of maps may be associated with a union.  These
404
maps correspond to functions which take the union, plus a number of
405
other map parameter types, and return the map return type.  They are
406
described as follows: 
407
<PRE>
408
	<I>map-group</I> :
409
		: [ <I>map-list<SUB>opt</SUB></I> ]
410
 
411
	<I>map</I> :
412
		<I>extended-type</I> #<I><SUB>opt</SUB> identifier</I> ( <I>parameter-list
413
<SUB>opt</SUB></I> )
414
 
415
	<I>map-list</I> :
416
		<I>map</I>
417
		<I>map-list map</I>
418
</PRE>
419
where: 
420
<PRE>
421
	<I>parameter-list</I> :
422
		<I>parameter-declarations</I>
423
		<I>parameter-list</I> ; <I>parameter-declarations</I>
424
 
425
	<I>parameter-declarations</I> :
426
		<I>extended-type parameter-declarators</I>
427
 
428
	<I>parameter-declarators</I> :
429
		<I>identifier</I>
430
		<I>parameter-declarators</I> , <I>identifier</I>
431
</PRE>
432
Note that the map parameter and return types are given by: 
433
<PRE>
434
	<I>extended-type</I> :
435
		<I>type</I>
436
		<I>quoted-type</I>
437
</PRE>
438
In addition to the <A HREF="#InputType">types derived from the algebra</A>
439
it is possible to use quoted C types in this context. 
440
</P>
441
<P>
442
A map may be qualified by means of a hash.  This means that the associated
443
function also takes a <A HREF="#OutputUnionMaps">destructor function</A>
444
as a parameter. 
445
</P>
446
 
447
<H3><A NAME="InputType">2.6. Type constructors</A></H3>
448
<P>
449
The types derived from the algebra may be described as follows: 
450
<PRE>
451
	<I>type</I> :
452
		<I>identifier</I>
453
		PTR <I>type</I>
454
		LIST <I>type</I>
455
		STACK <I>type</I>
456
		VEC <I>type</I>
457
		VEC_PTR <I>type</I>
458
</PRE>
459
The simple types correspond to primitive, identity, enumeration, structure
460
or union names.  It is possible for a type to be used before it is
461
defined, but it must be defined at some point. 
462
</P>
463
<P>
464
The derived type constructors correspond to pointers, lists, stacks,
465
vectors and pointers into vectors.  They may be used to build up further
466
types from the basic algebra types. 
467
</P>
468
 
469
<H3><A NAME="Module">2.7. Relations between algebras</A></H3>
470
<P>
471
As <A HREF="#Options">mentioned above</A>, more than one input algebra
472
may be specified to <CODE>calculus</CODE>.  Each is processed separately,
473
and output is generated for only one.  By default this is the last
474
algebra processed, however a specific algebra can be specified using
475
the command-line option <CODE>-A</CODE><I>name</I>, where <I>name</I>
476
is the name of the algebra to be used for output. 
477
</P>
478
<P>
479
Types may be imported from one algebra to another by means of commands
480
of the form: 
481
<PRE>
482
	<I>import</I> :
483
		IMPORT <I>identifier</I> ;
484
		IMPORT <I>identifier</I> :: <I>identifier</I> ;
485
</PRE>
486
which fit into the main syntax as an <I>item</I>.  The first form
487
imports all the types from the algebra given by <I>identifier</I>
488
into the current algebra.  The second imports a single type, given
489
by the second 
490
<I>identifier</I> from the algebra given by the first <I>identifier</I>.
491
</P>
492
<P>
493
Note that importing a type in this way also imports all the types
494
used in its construction.  This includes such things as structure
495
components and union fields and maps.  Thus an algebra consisting
496
just of 
497
<I>import</I> commands can be used to express subalgebras in a simple
498
fashion. 
499
</P>
500
 
501
<HR>
502
<H2><A NAME="TokenOutput">3. Output type system specification</A></H2>
503
<P>
504
In this section we document the basic output of <CODE>calculus</CODE>.
505
Two forms of the output can be generated - a description of the output
506
specification in terms of the TenDRA <CODE>#pragma token</CODE> constructs,
507
and the actual C code which implements these tokens. 
508
</P>
509
<P>
510
In this section the description given will be at the level of the
511
output specification.  The more important details of the <A HREF="#COutput">C
512
implementation</A> are given in the following section. 
513
</P>
514
<P>
515
The output is split among several header files in the specified output
516
directory.  The main output is printed into <I>name</I><CODE>.h</CODE>,
517
where <I>name</I> is the overall algebra name.  Unless otherwise stated,
518
all the objects specified below are to be found in <I>name</I><CODE>.h</CODE>.
519
However for each union, <I>union</I>, in the algebra certain information
520
associated with the union is printed into <I>union</I><CODE>_ops.h</CODE>.
521
If the union has any maps associated with it then further output is
522
printed to <I>union</I><CODE>_map.h</CODE> and <I>union</I><CODE>_hdr.h</CODE>.
523
</P>
524
 
525
<H3><A NAME="OutputInfo">3.1. Version information</A></H3>
526
<P>
527
Certain basic information about the input algebra is included in 
528
<I>name</I><CODE>.h</CODE>.  <I>name</I><CODE>_NAME</CODE> is a string
529
literal giving the overall algebra name.  <I>name</I><CODE>_VERSION</CODE>
530
is a string literal giving the algebra version number. 
531
<I>name</I><CODE>_SPECIFICATION</CODE> and 
532
<I>name</I><CODE>_IMPLEMENTATION</CODE> are flags which take the values
533
 
534
terms of <CODE>#pragma token</CODE> statements or the C implementation
535
is included. 
536
</P>
537
 
538
<H3><A NAME="OutputBasic">3.2. Basic types</A></H3>
539
<P>
540
Six abstract type operators, each taking a type as argument and returning
541
a type, are specified as follows: 
542
<PRE>
543
	TYPE PTR ( TYPE <I>t</I> );
544
	TYPE LIST ( TYPE <I>t</I> ) ;
545
	TYPE STACK ( TYPE <I>t</I> ) ;
546
	TYPE VEC ( TYPE <I>t</I> ) ;
547
	TYPE VEC_PTR ( TYPE <I>t</I> ) ;
548
	TYPE SIZE ( TYPE <I>t</I> ) ;
549
</PRE>
550
These represent a pointer to an object of type <I>t</I>, a list of
551
objects of type <I>t</I>, a stack of objects of type <I>t</I>, a vector
552
of objects of type <I>t</I>, a pointer into a vector of objects of
553
type <I>t</I>, and an allocation block size for type <I>t</I> respectively.
554
(It is possible to suppress all constructs involving <CODE>VEC</CODE>
555
or 
556
<CODE>VEC_PTR</CODE> by passing the <CODE>-x</CODE> command-line option
557
to <CODE>calculus</CODE>.  Similarly <CODE>STACK</CODE> constructs
558
may be suppressed using <CODE>-z</CODE>.) 
559
</P>
560
<P>
561
These constructors can be applied to any type, although in practice
562
they are only applied to the types specified in the algebra and those
563
derived from them.  For example, we may form the type: 
564
<PRE>
565
	LIST ( PTR ( int ) )
566
</PRE>
567
representing a list of pointers to <CODE>int</CODE>. 
568
</P>
569
<P>
570
An integral type: 
571
<PRE>
572
	INT_TYPE <I>name</I>_dim ;
573
</PRE>
574
is specified, where <I>name</I> is the overall algebra name.  This
575
type is used to represent the sizes of vectors. 
576
</P>
577
<P>
578
A function pointer type: 
579
<PRE>
580
	typedef void ( *DESTROYER ) () ;
581
</PRE>
582
is specified, which represents a destructor function.  Two destructor
583
functions are specified: 
584
<PRE>
585
	void destroy_<I>name</I> () ;
586
	void dummy_destroy_<I>name</I> () ;
587
</PRE>
588
where <I>name</I> is as above.  <CODE>destroy_</CODE><I>name</I> is
589
the default destructor, whereas <CODE>dummy_destroy_</CODE><I>name</I>
590
is a dummy destructor which has no effect.  The details of the arguments
591
passed to the destructors and so on are implementation dependent.
592
</P>
593
 
594
<H3><A NAME="OutputSize">3.3. Operations on sizes</A></H3>
595
<P>
596
The <CODE>SIZE</CODE> type constructor is used to represent a multiple
597
of the size of a type.  It is used, for example, in the 
598
<A HREF="#OutputPtr">pointer stepping construct</A> <CODE>STEP_ptr</CODE>
599
to specify the number of units the pointer is to be increased by.
600
Having a separate abstract type for the size of each type greatly
601
increases the scope for type checking of memory allocation, and other,
602
functions. 
603
</P>
604
<P>
605
For each basic type in the algebra (a primitive, a structure or a
606
union), there is a constant expression: 
607
<PRE>
608
	SIZE ( <I>t</I> ) SIZE_<I>type</I> ;
609
</PRE>
610
where <I>t</I> denotes the type itself, and <I>type</I> is the associated
611
type name. 
612
</P>
613
<P>
614
For the five other type constructors <A HREF="#OutputBasic">described
615
above</A> there are constant expressions: 
616
<PRE>
617
	SIZE ( PTR ( <I>t</I> ) ) SIZE_ptr ( TYPE <I>t</I> ) ;
618
	SIZE ( LIST ( <I>t</I> ) ) SIZE_list ( TYPE <I>t</I> ) ;
619
	SIZE ( STACK ( <I>t</I> ) ) SIZE_stack ( TYPE <I>t</I> ) ;
620
	SIZE ( VEC ( <I>t</I> ) ) SIZE_vec ( TYPE <I>t</I> ) ;
621
	SIZE ( VEC_PTR ( <I>t</I> ) ) SIZE_vec_ptr ( TYPE <I>t</I> ) ;
622
</PRE>
623
for any type <I>t</I>. 
624
</P>
625
<P>
626
These constructs allow the size of any type derived from the algebra
627
to be built up.  There is also a construct which corresponds to multiplying
628
the size of a type by a constant.  This takes the form: 
629
<PRE>
630
	SIZE ( <I>t</I> ) SCALE ( SIZE ( <I>t</I> ), INT_TYPE <I>itype</I> ) ;
631
</PRE>
632
for any type <I>t</I> and any integral type <I>itype</I>. 
633
</P>
634
 
635
<H3><A NAME="OutputPtr">3.4. Operations on pointers</A></H3>
636
<P>
637
The <CODE>PTR</CODE> type constructor is used to represent a pointer
638
to an object of type <I>t</I>.  It should be emphasised that this
639
construct is not in general implemented by means of the C pointer
640
construct. 
641
</P>
642
 
643
<H4>Simple pointer constructs</H4>
644
<P>
645
There are several simple operations on pointers, given as follows:
646
<PRE>
647
	PTR ( <I>t</I> ) NULL_ptr ( TYPE <I>t</I> ) ;
648
	int IS_NULL_ptr ( PTR ( <I>t</I> ) ) ;
649
	int EQ_ptr ( PTR ( <I>t</I> ), PTR ( <I>t</I> ) ) ;
650
	PTR ( <I>t</I> ) STEP_ptr ( PTR ( <I>t</I> ), SIZE ( <I>t</I> ) ) ;
651
</PRE>
652
The construct <CODE>NULL_ptr</CODE> is used to form the null pointer
653
to <I>t</I> for a type <I>t</I>.  This is a constant expression. 
654
<CODE>IS_NULL_ptr</CODE> can be used to test whether a given pointer
655
expression is a null pointer.  Similarly <CODE>EQ_ptr</CODE> checks
656
whether two pointers are equal (note that we can only compare pointers
657
to the same type).  Finally <CODE>STEP_ptr</CODE> can be used to add
658
a scalar value to a pointer. 
659
</P>
660
 
661
<H4>Unique pointers</H4>
662
<P>
663
There are also constructs for generating and destroying unique pointers:
664
<PRE>
665
	PTR ( <I>t</I> ) UNIQ_ptr ( TYPE <I>t</I> ) ;
666
	void DESTROY_UNIQ_ptr ( PTR ( <I>t</I> ) ) ;
667
</PRE>
668
A unique pointer is guaranteed to be different from all other undestroyed
669
pointers.  Dereferencing a unique pointer is undefined. 
670
</P>
671
 
672
<H4>Pointer construction and destruction</H4>
673
<P>
674
The constructs: 
675
<PRE>
676
	PTR ( <I>t</I> ) MAKE_ptr ( SIZE ( <I>t</I> ) ) ;
677
	void DESTROY_ptr ( PTR ( <I>t</I> ), SIZE ( <I>t</I> ) ) ;
678
</PRE>
679
are used to respectively create and destroy a pointer to a given type.
680
</P>
681
 
682
<H4>Assignment and dereference constructs</H4>
683
<P>
684
The constructs for assigning and dereferencing pointers have one of
685
two forms depending on the complexity of the type pointed to.  For
686
simple types, including primitive, enumeration and union types, they
687
have the form: 
688
<PRE>
689
	void COPY_<I>type</I> ( PTR ( <I>t</I> ), <I>t</I> ) ;
690
	<I>t</I> DEREF_<I>type</I> ( PTR ( <I>t</I> ) ) ;
691
</PRE>
692
where <I>t</I> is the type involved and <I>type</I> is the associated
693
short name. 
694
</P>
695
<P>
696
For more complex types, including structures, the assignment or dereference
697
cannot be done in a single expression, so the constructs are specified
698
to be statements as follows: 
699
<PRE>
700
	STATEMENT COPY_<I>type</I> ( PTR ( <I>t</I> ), <I>t</I> ) ;
701
	STATEMENT DEREF_<I>type</I> ( PTR ( <I>t</I> ), lvalue <I>t</I> ) ;
702
</PRE>
703
Here the <CODE>lvalue</CODE> type qualifier is used to indicate that
704
the statement argument is an assignable <CODE>lvalue</CODE>.  In this
705
case it should give the location of an object of type <I>t</I> into
706
which the pointer will be dereferenced. 
707
</P>
708
<P>
709
The appropriate assignment and dereference constructs are generated
710
for each of the basic algebra types (primitives, enumerations, structures
711
and unions).  In addition there are generic assignment and dereference
712
constructs for pointer types, list types, stack types, vector types
713
and vector pointer types.  The first three are of the first form above,
714
whereas the second two have the second form, as follows: 
715
<PRE>
716
	void COPY_ptr ( PTR ( PTR ( <I>t</I> ) ), PTR ( <I>t</I> ) ) ;
717
	PTR ( <I>t</I> ) DEREF_ptr ( PTR ( PTR ( <I>t</I> ) ) ) ;
718
	void COPY_list ( PTR ( LIST ( <I>t</I> ) ), LIST ( <I>t</I> ) ) ;
719
	LIST ( <I>t</I> ) DEREF_list ( PTR ( LIST ( <I>t</I> ) ) ) ;
720
	void COPY_stack ( PTR ( STACK ( <I>t</I> ) ), STACK ( <I>t</I> ) ) ;
721
	STACK ( <I>t</I> ) DEREF_stack ( PTR ( STACK ( <I>t</I> ) ) ) ;
722
	STATEMENT COPY_vec ( PTR ( VEC ( <I>t</I> ) ), VEC ( <I>t</I> ) ) ;
723
	STATEMENT DEREF_vec ( PTR ( VEC ( <I>t</I> ) ), lvalue VEC ( <I>t</I> ) ) ;
724
	STATEMENT COPY_vec_ptr ( PTR ( VEC_PTR ( <I>t</I> ) ), VEC_PTR ( <I>t</I> ) ) ;
725
	STATEMENT DEREF_vec_ptr ( PTR ( VEC_PTR ( <I>t</I> ) ), lvalue VEC_PTR ( <I>t
726
</I> ) ) ;
727
</PRE>
728
</P>
729
 
730
<H3><A NAME="OutputList">3.5. Operations on lists</A></H3>
731
<P>
732
The <CODE>LIST</CODE> type constructor is used to represent a list
733
of objects of type <I>t</I>. 
734
</P>
735
 
736
<H4>Simple list constructs</H4>
737
<P>
738
There are several simple list constructs: 
739
<PRE>
740
	LIST ( <I>t</I> ) NULL_list ( TYPE <I>t</I> ) ;
741
	int IS_NULL_list ( LIST ( <I>t</I> ) ) ;
742
	int EQ_list ( LIST ( <I>t</I> ), LIST ( <I>t</I> ) ) ;
743
	unsigned LENGTH_list ( LIST ( <I>t</I> ) ) ;
744
	PTR ( <I>t</I> ) HEAD_list ( LIST ( <I>t</I> ) ) ;
745
	LIST ( <I>t</I> ) TAIL_list ( LIST ( <I>t</I> ) ) ;
746
	PTR ( LIST ( <I>t</I> ) ) PTR_TAIL_list ( LIST ( <I>t</I> ) ) ;
747
	LIST ( <I>t</I> ) END_list ( LIST ( <I>t</I> ) ) ;
748
	LIST ( <I>t</I> ) REVERSE_list ( LIST ( <I>t</I> ) ) ;
749
	LIST ( <I>t</I> ) APPEND_list ( LIST ( <I>t</I> ), LIST ( <I>t</I> ) ) ;
750
</PRE>
751
Empty lists may be constructed or tested for.  <CODE>NULL_list</CODE>
752
is a constant expression.  Two lists may be checked for equality (note
753
that this is equality of lists, rather than element-wise equality).
754
The number of elements in a list can be found.  The head or tail (or
755
<CODE>car</CODE> and <CODE>cdr</CODE>) of a list may be formed.  The
756
end element of a list may be selected.  The order of the elements
757
in a list can be reversed.  One list can be appended to another. 
758
</P>
759
 
760
<H4>Unique lists</H4>
761
<P>
762
There are also constructs for generating and destroying unique lists:
763
<PRE>
764
	LIST ( <I>t</I> ) UNIQ_list ( TYPE <I>t</I> ) ;
765
	void DESTROY_UNIQ_list ( LIST ( <I>t</I> ) ) ;
766
</PRE>
767
A unique lists is guaranteed to be different from all other undestroyed
768
lists.  Taking the head or tail of a unique list is undefined. 
769
</P>
770
 
771
<H4>List construction and destruction</H4>
772
<P>
773
For each type <I>t</I> there are operations for constructing and deconstructing
774
lists.  For the basic types comprising the algebra these take the
775
form: 
776
<PRE>
777
	STATEMENT CONS_<I>type</I> ( <I>t</I>, LIST ( <I>t</I> ), lvalue LIST ( <I>t
778
</I> ) ) ;
779
	STATEMENT UN_CONS_<I>type</I> ( lvalue <I>t</I>, lvalue LIST ( <I>t</I> ), LIST ( 
780
<I>t</I> ) ) ;
781
	STATEMENT DESTROY_CONS_<I>type</I> ( DESTROYER, lvalue <I>t</I>, lvalue LIST ( 
782
<I>t</I> ), LIST ( <I>t</I> ) ) ;
783
</PRE>
784
where <I>type</I> is the short type name. 
785
</P>
786
<P>
787
The operation <CODE>CONS_</CODE><I>type</I> is used to build a list
788
whose head is the first argument and whose tail is the second argument.
789
This is assigned to the third argument.  <CODE>UN_CONS_</CODE><I>type</I>
790
reverses this process, decomposing a list into its head and its tail.
791
<CODE>DESTROY_CONS_</CODE><I>type</I> is similar, but it also applies
792
the given destructor function to the decomposed list component. 
793
</P>
794
<P>
795
There are also generic list construction and deconstruction operations
796
which apply to lists of pointers (with a <CODE>ptr</CODE> suffix),
797
lists of lists (with a <CODE>list</CODE> suffix), lists of stacks
798
(with a 
799
<CODE>stack</CODE> suffix), lists of vectors (with a <CODE>vec</CODE>
800
suffix) and lists of pointers to vectors (with a <CODE>vec_ptr</CODE>
801
suffix).  For example, for lists of pointers these have the form:
802
<PRE>
803
	STATEMENT CONS_ptr ( PTR ( <I>t</I> ), LIST ( PTR ( <I>t</I> ) ), lvalue LIST ( PTR ( 
804
<I>t</I> ) ) ) ;
805
	STATEMENT UN_CONS_ptr ( lvalue PTR ( <I>t</I> ), lvalue LIST ( PTR ( <I>t</I> ) ), LIST ( PTR ( 
806
<I>t</I> ) ) ) ;
807
	STATEMENT DESTROY_CONS_ptr ( DESTROYER, lvalue PTR ( <I>t</I> ), lvalue LIST ( PTR ( 
808
<I>t</I> ) ), LIST ( PTR ( <I>t</I> ) ) ) ;
809
</PRE>
810
There is also a generic list destruction construct: 
811
<PRE>
812
	STATEMENT DESTROY_list ( LIST ( <I>t</I> ), SIZE ( <I>t</I> ) ) ;
813
</PRE>
814
which may be used to destroy all the elements in a list. 
815
</P>
816
 
817
<H3><A NAME="OutputStack">3.6. Operations on stacks</A></H3>
818
<P>
819
The <CODE>STACK</CODE> type constructor is used to represent stacks
820
of objects of type <I>t</I>.  Empty stacks can be created and tested
821
for: 
822
<PRE>
823
	STACK ( <I>t</I> ) NULL_stack ( TYPE <I>t</I> ) ;
824
	int IS_NULL_stack ( STACK ( <I>t</I> ) ) ;
825
</PRE>
826
For each type <I>t</I> there are operations for pushing objects onto
827
a stack and for popping elements off.  For the basic types comprising
828
the algebra these take the form: 
829
<PRE>
830
	STATEMENT PUSH_<I>type</I> ( <I>t</I>, lvalue STACK ( <I>t</I> ) ) ;
831
	STATEMENT POP_<I>type</I> ( lvalue <I>t</I>, lvalue STACK ( <I>t</I> ) ) ;
832
</PRE>
833
where <I>type</I> is the short type name.  There are also generic
834
constructs, such as <CODE>PUSH_ptr</CODE> for pushing any pointer
835
type, similar to the <A HREF="#OutputList">generic list constructors</A>
836
above. 
837
</P>
838
<P>
839
Stacks are in fact just modified lists with pushing corresponding
840
adding an element to the start of a list, and popping to removing
841
the first element.  There are constructs: 
842
<PRE>
843
	LIST ( <I>t</I> ) LIST_stack ( STACK ( <I>t</I> ) ) ;
844
	STACK ( <I>t</I> ) STACK_list ( LIST ( <I>t</I> ) ) ;
845
</PRE>
846
for explicitly converting between lists and stacks. 
847
</P>
848
 
849
<H3><A NAME="OutputVec">3.7. Operations on vectors</A></H3>
850
<P>
851
The <CODE>VEC</CODE> type constructor is used to represent vectors
852
of objects of type <I>t</I>.  There are a number of simple operations
853
on vectors: 
854
<PRE>
855
	VEC ( <I>t</I> ) NULL_vec ( TYPE <I>t</I> ) ;
856
	<I>name</I>_dim DIM_vec ( VEC ( <I>t</I> ) ) ;
857
	<I>name</I>_dim DIM_ptr_vec ( PTR ( VEC ( <I>t</I> ) ) ) ;
858
	PTR ( <I>t</I> ) PTR_ptr_vec ( PTR ( VEC ( <I>t</I> ) ) ) ;
859
</PRE>
860
An empty vector can be constructed (note that, unlike null pointers
861
and null lists, this is not a constant expression).  The number of
862
elements in a vector (or in a vector given by a pointer) can be determined
863
(note how the type <I>name</I><CODE>_dim</CODE> is used to represent
864
vector sizes).  A pointer to a vector can be transformed into a pointer
865
to the elements of the vector. 
866
</P>
867
<P>
868
In general a vector may be created or destroyed using the operators:
869
<PRE>
870
	STATEMENT MAKE_vec ( SIZE ( <I>t</I> ), <I>name</I>_dim, lvalue VEC ( <I>t</I> ) ) ;
871
	STATEMENT DESTROY_vec ( VEC ( <I>t</I> ), SIZE ( <I>t</I> ) ) ;
872
</PRE>
873
Finally a vector can be trimmed using: 
874
<PRE>
875
	STATEMENT TRIM_vec ( VEC ( <I>t</I> ), SIZE ( <I>t</I> ), int, int, lvalue VEC ( 
876
<I>t</I> ) ) ;
877
</PRE>
878
the two integral arguments giving the lower and upper bounds for the
879
trimming operation. 
880
</P>
881
 
882
<H3><A NAME="OutputVecPtr">3.8. Operations on vector pointers</A></H3>
883
<P>
884
The <CODE>VEC_PTR</CODE> type constructor is used to represent a pointer
885
to an element of a vector of objects of type <I>t</I>.  Apart from
886
the basic constructors already mentioned, there are only two operations
887
on vector pointers: 
888
<PRE>
889
	VEC_PTR ( <I>t</I> ) VEC_PTR_vec ( VEC ( <I>t</I> ) ) ;
890
	PTR ( <I>t</I> ) PTR_vec_ptr ( VEC_PTR ( <I>t</I> ) ) ;
891
</PRE>
892
The first transforms a vector into a vector pointer (pointing to its
893
first argument).  The second transforms a vector pointer into a normal
894
pointer. 
895
</P>
896
 
897
<H3><A NAME="OutputPrim">3.9. Operations on primitives</A></H3>
898
<P>
899
Each primitive specified within the algebra maps onto a <CODE>typedef</CODE>
900
defining the type in terms of its given definition.  The only operations
901
on primitives are those listed above - the size constructs, the pointer
902
assignment and dereference operations, the list construction and deconstruction
903
operations and the stack push and pop operations. 
904
</P>
905
 
906
<H3><A NAME="OutputIdent">3.10. Operations on identities</A></H3>
907
<P>
908
Each identity specified within the algebra maps onto a <CODE>typedef</CODE>
909
in the output file.  There are no operations on identities. 
910
</P>
911
 
912
<H3><A NAME="OutputEnum">3.11. Operations on enumerations</A></H3>
913
<P>
914
Each enumeration specified within the algebra maps onto an unsigned
915
integral type in the output file.  The <A HREF="#OutputPrim">basic
916
operations</A> listed above are always generated unless it has been
917
indicated that <A HREF="#InputEnum">no lists of this type will be
918
formed</A>, when <CODE>CONS_</CODE><I>type</I> and the other list
919
and stack operators are suppressed.  In addition each enumerator which
920
is a member of this enumeration maps onto a constant expression: 
921
<PRE>
922
	<I>t enum_member</I> ;
923
</PRE>
924
where <I>t</I> is the enumeration type, <I>enum</I> is the short type
925
name, and <I>member</I> is the enumerator name.  It is guaranteed
926
that the first enumerator will have value 0, the second 1, and so
927
on, unless the value of the enumerator is explicitly given (as in
928
C).  There is also a constant expression: 
929
<PRE>
930
	unsigned long ORDER_<I>enum</I> ;
931
</PRE>
932
giving one more than the maximum enumerator in the enumeration. 
933
</P>
934
 
935
<H3><A NAME="OutputStruct">3.12. Operations on structures</A></H3>
936
<P>
937
Each structure specified within the algebra maps onto a <CODE>typedef</CODE>
938
defining the type to be the C structure with the given components.
939
In addition to the <A HREF="#OutputPrim">basic operations</A> listed
940
above there are also field selectors defined. 
941
</P>
942
<P>
943
Suppose that <I>t</I> is a structure type with short name <I>struct</I>,
944
and that <I>comp</I> is a component of <I>t</I> of type <I>ctype</I>.
945
Then there is an operation: 
946
<PRE>
947
	PTR ( <I>ctype</I> ) <I>struct_comp</I> ( PTR ( <I>t</I> ) ) ;
948
</PRE>
949
which transforms a pointer to the structure into a pointer to the
950
component.  There is also an operation: 
951
<PRE>
952
	STATEMENT MAKE_<I>struct</I> ( <I>ctype</I>, ...., PTR ( <I>t</I> ) ) ;
953
</PRE>
954
where <I>ctype</I> ranges over all the component types which do not
955
have a component initialiser string in the structure definition. 
956
This is used to assign values to all the components of a structure.
957
If a component has an initialiser string then this is used as an expression
958
giving the initial value, otherwise the given operation argument is
959
used.  The initialiser strings are evaluated in the context of the
960
<CODE>MAKE_</CODE><I>struct</I> statement.  The parameters to the
961
operation may be referred to by the corresponding component name followed
962
by <CODE>_</CODE>.  The partially initialised object may be referred
963
to by the special character sequence <CODE>%0</CODE>.  Any remainder
964
operations should be written as <CODE>%%</CODE> rather than <CODE>%</CODE>.
965
</P>
966
<P>
967
Inheritance in structures is handled as follows: if <I>t</I> is a
968
derived structure with base structure <I>btype</I> then there is an
969
operation: 
970
<PRE>
971
	PTR ( <I>btype</I> ) CONVERT_<I>struct_base</I> ( PTR ( <I>t</I> ) ) ;
972
</PRE>
973
where <I>struct</I> and <I>base</I> are the short names of <I>t</I>
974
and 
975
<I>btype</I> respectively. 
976
</P>
977
 
978
<H3><A NAME="OutputUnion">3.13. Operations on unions</A></H3>
979
<P>
980
Each union specified within the algebra maps onto an opaque type in
981
the output file.  In addition to the <A HREF="#OutputPrim">basic operations</A>
982
listed above there are a number of other constructs output into 
983
<I>name</I><CODE>.h</CODE>, namely: 
984
<PRE>
985
	unsigned int ORDER_<I>union</I> ;
986
	<I>t</I> NULL_<I>union</I> ;
987
	int IS_NULL_<I>union</I> ( <I>t</I> ) ;
988
	int EQ_<I>union</I> ( <I>t</I>, <I>t</I> ) ;
989
</PRE>
990
where <I>t</I> denotes the union type, and <I>union</I> is the short
991
type name.  <CODE>ORDER_</CODE><I>union</I> is a constant value giving
992
the number of union fields.  <CODE>NULL_</CODE><I>union</I> is a distinguished
993
constant value of type <I>t</I>.  Values of type <I>t</I> may be compared
994
against this distinguished value, or against each other. 
995
</P>
996
 
997
<H4>Union construction operations</H4>
998
<P>
999
Most of the output for the union type <I>t</I> is output into the
1000
file 
1001
<I>union</I><CODE>_ops.h</CODE>.  This contains a construct: 
1002
<PRE>
1003
	unsigned int TAG_<I>union</I> ( <I>t</I> ) ;
1004
</PRE>
1005
for extracting the discriminant tag from a union. 
1006
</P>
1007
<P>
1008
For each shared component, <I>comp</I>, of <I>t</I> of type <I>ctype</I>,
1009
say, there is an operator: 
1010
<PRE>
1011
	PTR ( <I>ctype</I> ) <I>union_comp</I> ( <I>t</I> ) ;
1012
</PRE>
1013
which extracts this component from the union. 
1014
</P>
1015
<P>
1016
For each field, <I>field</I>, of the union there are constructs: 
1017
<PRE>
1018
	unsigned int <I>union_field</I>_tag ;
1019
	int IS_<I>union_field</I> ( <I>t</I> ) ;
1020
</PRE>
1021
giving the (constant) discriminant tag associated with this field,
1022
and a test for whether an object of type <I>t</I> has this discriminant.
1023
</P>
1024
<P>
1025
In addition, for each unshared component, <I>comp</I>, of <I>field</I>
1026
of type <I>ctype</I>, say, there is an operator: 
1027
<PRE>
1028
	PTR ( <I>ctype</I> ) <I>union_field_comp</I> ( <I>t</I> ) ;
1029
</PRE>
1030
which extracts this component from the union. 
1031
</P>
1032
<P>
1033
There are also operations for constructing and deconstructing objects
1034
of type <I>t</I> for field <I>field</I> given as follows: 
1035
<PRE>
1036
	STATEMENT MAKE_<I>union_field</I> ( <I>ctype</I>, ...., lvalue <I>t</I> ) ;
1037
	STATEMENT DECONS_<I>union_field</I> ( lvalue <I>ctype</I>, ...., <I>t</I> ) ;
1038
	STATEMENT DESTROY_<I>union_field</I> ( DESTROYER, lvalue <I>ctype</I>, ...., 
1039
<I>t</I> ) ;
1040
</PRE>
1041
The operation <CODE>MAKE_</CODE><I>union_field</I> constructs a value
1042
of type <I>t</I> from the various components and assigns it into the
1043
last argument.  The <I>ctype</I> arguments range over all the components
1044
of 
1045
<I>field</I>, both the shared components and the unshared components,
1046
which do not have a component initialiser string in the definition.
1047
The union component are initialised either using the 
1048
<A HREF="#OutputStruct">initialiser string</A> or the given operation
1049
argument. 
1050
</P>
1051
<P>
1052
<CODE>DECONS_</CODE><I>union_field</I> performs the opposite operation,
1053
deconstructing an object of type <I>t</I> into its components for
1054
this field.  <CODE>DESTROY_</CODE><I>union_field</I> is similar, except
1055
that it also applies the given destructor function to the original
1056
value.  For these two operations <I>ctype</I> ranges over all the
1057
components, including those with initialiser strings. 
1058
</P>
1059
 
1060
<H4>Union field sets</H4>
1061
<P>
1062
Recall that <A HREF="#InputUnion">a number of union field identifiers</A>
1063
may be associated with the same set of components.  In this case these
1064
fields form a union field set named after the first element of the
1065
set. There are operations: 
1066
<PRE>
1067
	int IS_<I>union_field</I>_etc ( <I>t</I> ) ;
1068
	PTR ( <I>ctype</I> ) <I>union_field</I>_etc_<I>comp</I> ( <I>t</I> ) ;
1069
	STATEMENT MAKE_<I>union_field</I>_etc ( unsigned int, <I>ctype</I>, ...., lvalue 
1070
<I>t</I> ) ;
1071
	STATEMENT MODIFY_<I>union_field</I>_etc ( unsigned int, <I>t</I> ) ;
1072
	STATEMENT DECONS_<I>union_field</I>_etc ( lvalue <I>ctype</I>, ...., <I>t</I> ) ;
1073
	STATEMENT DESTROY_<I>union_field</I>_etc ( DESTROYER, lvalue <I>ctype</I>, ...., 
1074
<I>t</I> ) ;
1075
</PRE>
1076
defined on these sets.  These are exactly analogous to the single
1077
field operations except that they work for any field in the set. 
1078
Note that 
1079
<CODE>MAKE_</CODE><I>union_field</I><CODE>_etc</CODE> takes an extra
1080
argument, giving the tag associated with the particular element of
1081
the set being constructed.  Also the construct 
1082
<CODE>MODIFY_</CODE><I>union_field</I><CODE>_etc</CODE> is introduced
1083
to allow the tag of an existing object to be modified to another value
1084
within the same set. 
1085
</P>
1086
<P>
1087
The valid range of union tags for this set can be given by the two
1088
constants: 
1089
<PRE>
1090
	unsigned int <I>union_field</I>_tag ;
1091
	unsigned int <I>union_field</I>_etc_tag ;
1092
</PRE>
1093
A union is a member of this set if its tag is greater than or equal
1094
to <I>union_field</I><CODE>_tag</CODE> and strictly less than 
1095
<I>union_field</I><CODE>_etc_tag</CODE>. 
1096
</P>
1097
 
1098
<H4>Inheritance in unions</H4>
1099
<P>
1100
Inheritance in unions is handled as follows: if <I>t</I> is a derived
1101
union with base union <I>btype</I> then there is an operation: 
1102
<PRE>
1103
	<I>btype</I> CONVERT_<I>union_base</I> ( <I>t</I> ) ;
1104
</PRE>
1105
where <I>union</I> and <I>base</I> are the short names of <I>t</I>
1106
and 
1107
<I>btype</I> respectively. 
1108
</P>
1109
 
1110
<H4><A NAME="OutputUnionMaps">Union maps</A></H4>
1111
<P>
1112
For each map, <I>map</I>, on the union <I>t</I>, we have declared
1113
in 
1114
<I>union</I><CODE>_ops.h</CODE> an operator: 
1115
<PRE>
1116
	<I>map_ret map_union</I> ( <I>t</I>, <I>map_par</I>, .... ) ;
1117
</PRE>
1118
where <I>map_ret</I> is the map return type and <I>map_par</I> ranges
1119
over the map parameter types.  This is except for maps with destructors
1120
(i.e. those qualified by a <A HREF="#InputUnion">hash symbol</A>)
1121
which have the form: 
1122
<PRE>
1123
	<I>map_ret map_union</I> ( <I>t</I>, DESTROYER, <I>map_par</I>, .... ) ;
1124
</PRE>
1125
These maps are implemented by having one function per field for each
1126
map. The output file <I>union</I><CODE>_map.h</CODE> contains tables
1127
of these functions.  These have the form: 
1128
<PRE>
1129
	<I>map_ret</I> ( *<I>map_union</I>_table [ ORDER_<I>union</I> ] ) ( <I>t</I>, 
1130
<I>map_par</I>, .... ) = {
1131
		....
1132
		<I>map_union_field</I>,
1133
		....
1134
	} ;
1135
</PRE>
1136
where there is one entry per union field. 
1137
</P>
1138
<P>
1139
In order to aid the construction of these functions a set of function
1140
headers is provided in <I>union</I><CODE>_hdr.h</CODE>.  These take
1141
the form: 
1142
<PRE>
1143
	#define HDR_<I>map_union_field</I>\
1144
		<I>map_ret map_union_field</I> ( <I>name_union</I>, <I>destroyer</I>, <I>par
1145
</I>, .... )\
1146
		<I>t name_union</I> ;\
1147
		DESTROYER <I>destroyer</I> ; /* if required */\
1148
		<I>map_par par</I> ;\
1149
		....\
1150
		{\
1151
			<I>ctype comp</I> ;\
1152
			....\
1153
			DECONS_<I>union_field</I> ( <I>comp</I>, ...., <I>name_union</I> ) ;
1154
</PRE>
1155
There is also an alternative function header, 
1156
<CODE>HDR_</CODE><I>map</I>_d_<I>union_field</I>, which calls 
1157
<CODE>DESTROY_</CODE><I>union_field</I> rather than 
1158
<CODE>DECONS_</CODE><I>union_field</I>.  The destructor function used
1159
is 
1160
<I>destroyer</I>, if this parameter is present, or the default destructor,
1161
<CODE>destroy_</CODE><I>name</I>, otherwise. 
1162
</P>
1163
 
1164
<HR>
1165
<H2><A NAME="COutput">4. Implementation details</A></H2>
1166
 
1167
<H3><A NAME="COutputTypes">4.1. Implementation of types</A></H3>
1168
<P>
1169
The C implementation of the type system <A HREF="#TokenOutput">specified
1170
above</A> is based on a single type, <I>name</I>, with the same name
1171
as the input algebra.  This is defined as follows: 
1172
<PRE>
1173
	typedef union <I>name</I>_tag {
1174
		unsigned int ag_tag ;
1175
		union <I>name</I>_tag *ag_ptr ;
1176
		unsigned ag_enum ;
1177
		unsigned long ag_long_enum ;
1178
		<I>name</I>_dim ag_dim ;
1179
		<I>t</I> ag_prim_<I>type</I> ;
1180
		....
1181
	} <I>name</I> ;
1182
</PRE>
1183
where <I>t</I> runs over all the primitive types.  All of the types
1184
in the algebra can be packed into a block of cells of type <I>name</I>.
1185
The following paragraphs describe the implementation of each type,
1186
together with how they are packed as blocks of cells.  This is illustrated
1187
by the following diagram: 
1188
<CENTER>
1189
<IMG SRC="../images/calc.gif" ALT="Packing of types">
1190
</CENTER>
1191
</P>
1192
<P>
1193
Primitive types are implemented by a <CODE>typedef</CODE> defining
1194
the type in terms of its <A HREF="#OutputPrim">given definition</A>.
1195
A primitive type can be packed into a single cell using the appropriate
1196
<CODE>ag_prim_</CODE><I>type</I> field of the union. 
1197
</P>
1198
<P>
1199
Identity types are implemented by a <CODE>typedef</CODE> defining
1200
the type as being equal to another <A HREF="#OutputIdent">type from
1201
the algebra</A>. 
1202
</P>
1203
<P>
1204
Enumeration types are all implemented as <CODE>unsigned int</CODE>
1205
if all its values fit into 16 bits, or <CODE>unsigned long</CODE>
1206
otherwise.  An enumeration type can be packed into a single cell using
1207
the 
1208
<CODE>ag_enum</CODE> or <CODE>ag_long_enum</CODE> field of the union.
1209
</P>
1210
<P>
1211
Structure types are implemented by a <CODE>typedef</CODE> defining
1212
the type to be the C structure with the <A HREF="#OutputStruct">given
1213
components</A>.  A structure type may be packed into a block of cells
1214
by packing each of the components in turn. 
1215
</P>
1216
<P>
1217
Union types are all implemented by a pointer to <I>name</I>.  This
1218
pointer references a block of cells.  The null pointer represents
1219
<CODE>NULL_</CODE><I>union</I>, otherwise the first cell contains
1220
the union discriminant tag (in the <CODE>ag_tag</CODE> field), with
1221
the subsequent cells containing the packed field components (shared
1222
components first, then unshared components).  If the union has only
1223
one field then the discriminant can be omitted.  The union itself
1224
can be packed into a single cell using the <CODE>ag_ptr</CODE> field
1225
of the union. 
1226
</P>
1227
<P>
1228
Pointer types are all implemented by a pointer to <I>name</I>.  Null
1229
pointers represent <CODE>NULL_ptr</CODE>, otherwise the pointer references
1230
a single cell.  This cell contains a pointer to the packed version
1231
of the object being pointed to in its <CODE>ag_ptr</CODE> field. 
1232
A pointer type itself can be packed into a single cell using the <CODE>ag_ptr
1233
</CODE>
1234
field of the union. 
1235
</P>
1236
<P>
1237
List types are all implemented by a pointer to <I>name</I>.  Null
1238
pointers represent <CODE>NULL_list</CODE>, otherwise the pointer references
1239
a block of two cells.  The first cell gives the tail of the list in
1240
its <CODE>ag_ptr</CODE> field; the second cell contains a pointer
1241
to the packed version of the head of the list in its <CODE>ag_ptr</CODE>
1242
field. A list type itself can be packed into a single cell using the
1243
<CODE>ag_ptr</CODE> field of the union. 
1244
</P>
1245
<P>
1246
Stack types are identical to list types, with the head of the list
1247
corresponding to the top of the stack. 
1248
</P>
1249
<P>
1250
Vector pointer and vector types are all implemented by structures
1251
defined as follows: 
1252
<PRE>
1253
	typedef unsigned int <I>name</I>_dim ;
1254
 
1255
	typedef struct {
1256
		<I>name</I> *vec ;
1257
		<I>name</I> *ptr ;
1258
	} <I>name</I>_VEC_PTR ;
1259
 
1260
	typedef struct {
1261
		<I>name</I>_dim dim ;
1262
		<I>name</I>_VEC_PTR elems ;
1263
	} <I>name</I>_VEC ;
1264
</PRE>
1265
The <CODE>vec</CODE> field of a vector pointer contains a pointer
1266
to a block of cells containing the packed versions of the elements
1267
of the vector. The <CODE>ptr</CODE> field is a pointer to the current
1268
element of this block. A vector type also has a field giving the vector
1269
size.  A vector pointer type can be packed into a block of two cells,
1270
using the <CODE>ag_ptr</CODE>
1271
field of each to hold its two components.  A vector type can similarly
1272
be packed into a block of three cells, the first holding the vector
1273
size in its <CODE>ag_dim</CODE> field. 
1274
</P>
1275
<P>
1276
All size types are implemented as <CODE>int</CODE>. 
1277
</P>
1278
 
1279
<H3><A NAME="COutputSupport">4.2. Support routines</A></H3>
1280
<P>
1281
The implementation requires the user to provide certain support functions.
1282
Most fundamental are the routines for allocating and deallocating
1283
the blocks of cells which are used to store the types.  These are
1284
specified as follows: 
1285
<PRE>
1286
	<I>name</I> *gen_<I>name</I> ( unsigned int ) ;
1287
	void destroy_<I>name</I> ( <I>name</I> *, unsigned int ) ;
1288
	void dummy_destroy_<I>name</I> ( <I>name</I> *, unsigned int ) ;
1289
</PRE>
1290
where <CODE>gen_</CODE><I>name</I> allocates a block of cells of the
1291
given size, <CODE>destroy_</CODE><I>name</I> deallocates the given
1292
block, and 
1293
<CODE>dummy_destroy_</CODE><I>name</I> has <A HREF="#OutputBasic">no
1294
effect</A>.  The precise details of how the memory management is to
1295
be handled are left to the user. 
1296
</P>
1297
<P>
1298
Certain generic list functions must also be provided, namely: 
1299
<PRE>
1300
	void destroy_<I>name</I>_list ( <I>name</I> *, unsigned int ) ;
1301
	name *reverse_<I>name</I>_list ( <I>name</I> * ) ;
1302
	name *append_<I>name</I>_list ( <I>name</I> *, <I>name</I> * ) ;
1303
	name *end_<I>name</I>_list ( <I>name</I> * ) ;
1304
</PRE>
1305
which implement the constructs <CODE>DESTROY_list</CODE>, 
1306
<CODE>REVERSE_list</CODE>, <CODE>APPEND_list</CODE> and 
1307
<CODE>END_list</CODE> respectively. 
1308
</P>
1309
<P>
1310
Finally a dummy empty vector: 
1311
<PRE>
1312
	<I>name</I>_VEC empty_<I>name</I>_vec ;
1313
</PRE>
1314
needs to be defined. 
1315
</P>
1316
<P>
1317
Examples of these support routines can be found in the 
1318
<A HREF="#Example"><CODE>calculus</CODE> program</A> itself. 
1319
</P>
1320
 
1321
<H3><A NAME="COutputAssert">4.3. Run-time checking</A></H3>
1322
<P>
1323
The type checking facilities supported by <CODE>calculus</CODE> allow
1324
for compile-time detection of many potential programming errors, however
1325
there are many problems, such as dereferencing null pointers, deconstructing
1326
empty lists and union tag errors which can only be detected at run-time.
1327
For this reason <CODE>calculus</CODE> can be made to add extra assertions
1328
to check for such errors into its output.  This is done by specifying
1329
the <CODE>-a</CODE> command-line option. 
1330
</P>
1331
<P>
1332
These assertions are implemented by means of macros.  If the macro
1333
<CODE>ASSERTS</CODE> is defined then these macros expand to give the
1334
run-time checks.  If not the output is exactly equivalent to that
1335
which would have been output if the <CODE>-a</CODE> option had not
1336
been given. 
1337
</P>
1338
<P>
1339
The assertions require certain support functions which are output
1340
into a separate file, <CODE>assert_def.h</CODE>.  These functions
1341
need to be compiled into the program when <CODE>ASSERTS</CODE> is
1342
defined.  Note that the functions are implementation specific. 
1343
</P>
1344
 
1345
<HR>
1346
<H2><A NAME="DiskOutput">5. Disk reading and writing</A></H2>
1347
<P>
1348
One of the facilities which the <A HREF="#COutputTypes">homogeneous
1349
implementation</A> of the type system described above allows for is
1350
the addition of persistence.  Persistence in this context means allowing
1351
objects to be written to, and read from, disk.  Also discussed in
1352
this section is the related topic of the object printing routines,
1353
which allow a human readable representation of objects of the type
1354
system to be output for debugging or other purposes. 
1355
</P>
1356
<P>
1357
The disk reading and writing routines are output into the files 
1358
<CODE>read_def.h</CODE> and <CODE>write_def.h</CODE> respectively
1359
if the 
1360
<CODE>-d</CODE> command-line option is passed to <CODE>calculus</CODE>.
1361
The object printing routines are output if the <CODE>-p</CODE> option
1362
is given, with additional code designed for use with run-time debuggers
1363
being added if the <CODE>-a</CODE> option is also given. 
1364
</P>
1365
<P>
1366
All of these routines use extra constructs output in the main output
1367
files (<I>name</I><CODE>.h</CODE> and <I>union</I><CODE>_ops.h</CODE>),
1368
but not normally accessible.  The macro <I>name</I><CODE>_IO_ROUTINES</CODE>
1369
should be defined in order to make these available for the disk reading
1370
and writing routines to use. 
1371
</P>
1372
 
1373
<H3><A NAME="DiskWrite">5.1. Disk writing routines</A></H3>
1374
<P>
1375
The disk writing routines output in <CODE>write_def.h</CODE> consist
1376
of a function: 
1377
<PRE>
1378
	static void WRITE_<I>type</I> ( <I>t</I> ) ;
1379
</PRE>
1380
for each type <I>t</I> mentioned within the algebra description, which
1381
writes an object of that type to disk. 
1382
</P>
1383
<P>
1384
Note that such routines are output not only for the basic types, such
1385
as unions and structures, but also for any composite types, such as
1386
pointers and lists, which are used in their definition.  The <I>type</I>
1387
component of the name <CODE>WRITE_</CODE><I>type</I> is derived from
1388
basic types <I>t</I> by using the short type name.  For composite
1389
types it is defined recursively as follows: 
1390
<PRE>
1391
	LIST ( <I>t</I> ) -&gt; list_<I>type</I>
1392
	PTR ( <I>t</I> ) -&gt; ptr_<I>type</I>
1393
	STACK ( <I>t</I> ) -&gt; stack_<I>type</I>
1394
	VEC ( <I>t</I> ) -&gt; vec_<I>type</I>
1395
	VEC_PTR ( <I>t</I> ) -&gt; vptr_<I>type</I>
1396
</PRE>
1397
Such functions are defined for identity types and composite types
1398
involving identity types by means of macros which define them in terms
1399
of the identity definitions.  <CODE>WRITE_</CODE><I>type</I> functions
1400
for the primitive types should be provided by the user to form a foundation
1401
on which all the other functions may be built. 
1402
</P>
1403
<P>
1404
The user may wish to generate <CODE>WRITE_</CODE><I>type</I> (or other
1405
disk reading and writing) functions for types other than those mentioned
1406
in the algebra definition.  This can be done by means of a command-line
1407
option of the form <CODE>-E</CODE><I>input</I> where <I>input</I>
1408
is a file containing a list of the extra types required.  In the notation
1409
<A HREF="#TextInput">used above</A> the syntax for <I>input</I> is
1410
given by: 
1411
<PRE>
1412
	<I>extra</I> :
1413
		<I>type-list<SUB>opt</SUB></I>
1414
 
1415
	<I>type-list</I> :
1416
		<I>type</I> ;
1417
		<I>type-list type</I> ;
1418
</PRE>
1419
The <CODE>WRITE_</CODE><I>type</I> functions are defined recursively
1420
in an obvious fashion.  The user needs to provide the writing routines
1421
for the primitives already mentioned, plus support routines (or macros):
1422
<PRE>
1423
	void WRITE_BITS ( int, unsigned int ) ;
1424
	void WRITE_DIM ( <I>name</I>_dim ) ;
1425
	void WRITE_ALIAS ( unsigned int ) ;
1426
</PRE>
1427
for writing a number of bits to disk, writing a vector dimension and
1428
writing an <A HREF="#DiskAlias">object alias</A>. 
1429
</P>
1430
<P>
1431
Any of the <CODE>WRITE_</CODE><I>type</I> functions may be overridden
1432
by the user by defining a macro <CODE>WRITE_</CODE><I>type</I> with
1433
the desired effect.  Note that the <CODE>WRITE_</CODE><I>type</I>
1434
function for an identity can be overridden independently of the function
1435
for the identity definition.  This provides a method for introducing
1436
types which are representationally the same, but which are treated
1437
differently by the disk reading and writing routines. 
1438
</P>
1439
 
1440
<H3><A NAME="DiskRead">5.2. Disk reading routines</A></H3>
1441
<P>
1442
The disk reading routines output in <CODE>read_def.h</CODE> are exactly
1443
analogous to the disk writing routines.  For each type <I>t</I> (except
1444
primitives) there is a function or macro: 
1445
<PRE>
1446
	static <I>t</I> READ_<I>type</I> ( void ) ;
1447
</PRE>
1448
which reads an object of that type from disk.  The user must provide
1449
the <CODE>READ_</CODE><I>type</I> functions for the primitive types,
1450
plus support routines: 
1451
<PRE>
1452
	unsigned int READ_BITS ( int ) ;
1453
	<I>name</I>_dim READ_DIM ( void ) ;
1454
	unsigned int READ_ALIAS ( void ) ;
1455
</PRE>
1456
for reading a number of bits from disk, reading a vector dimension
1457
and reading an <A HREF="#DiskAlias">object alias</A>.  The 
1458
<CODE>READ_</CODE><I>type</I> functions may be overridden by means
1459
of macros as before. 
1460
</P>
1461
 
1462
<H3><A NAME="DiskPrint">5.3. Object printing routines</A></H3>
1463
<P>
1464
The object printing routines output in <CODE>print_def.h</CODE> consist
1465
of a function or macro: 
1466
<PRE>
1467
	static void PRINT_<I>type</I> ( FILE *, <I>t</I>, char *, int ) ;
1468
</PRE>
1469
for each type <I>t</I>, which prints an object of type <I>t</I> to
1470
the given file, using the given object name and indentation value.
1471
The user needs to provide basic output routines: 
1472
<PRE>
1473
	void OUTPUT_<I>type</I> ( FILE *, <I>t</I> ) ;
1474
</PRE>
1475
for each primitive type.  The <CODE>PRINT_</CODE><I>type</I> functions
1476
may be overridden by means of macros as before. 
1477
</P>
1478
<P>
1479
The printing routines are under the control of three variables defined
1480
as follows: 
1481
<PRE>
1482
	static int print_indent_step = 4 ;
1483
	static int print_ptr_depth = 1 ;
1484
	static int print_list_expand = 0 ;
1485
</PRE>
1486
These determine the indentation to be used in the output, to what
1487
depth pointers are to be dereferenced when printing, and whether lists
1488
and stacks are to be fully expanded into a sequence of elements or
1489
just split into a head and a tail. 
1490
</P>
1491
<P>
1492
One application of these object printing routines is to aid debugging
1493
programs written using the <CODE>calculus</CODE> tool.  The form of
1494
the type system implementation means that it is not easy to extract
1495
information using run-time debuggers without a detailed knowledge
1496
of the structure of this implementation.  As a more convenient alternative,
1497
if both the 
1498
<CODE>-p</CODE> and <CODE>-a</CODE> command-line options are given
1499
then 
1500
<CODE>calculus</CODE> will generate functions: 
1501
<PRE>
1502
	void DEBUG_<I>type</I> ( <I>t</I> ) ;
1503
</PRE>
1504
defined in terms of <CODE>PRINT_</CODE><I>type</I>, for printing an
1505
object of the given type to the standard output.  Many debuggers have
1506
problems passing structure arguments, so for structure, vector and
1507
vector pointer types <CODE>DEBUG_</CODE><I>type</I> takes the form:
1508
<PRE>
1509
	void DEBUG_<I>type</I> ( <I>t</I> * ) ;
1510
</PRE>
1511
These debugging routines are only defined conditionally, if the macro
1512
<CODE>DEBUG</CODE> is defined. 
1513
</P>
1514
 
1515
<H3><A NAME="DiskAlias">5.4. Aliasing</A></H3>
1516
<P>
1517
An important feature of the disk reading and writing routines, namely
1518
aliasing, has been mentioned but not yet described.  The problem to
1519
be faced is that many of the objects built up using type systems defined
1520
using <CODE>calculus</CODE> will be cyclic - they will include references
1521
to themselves in their own definitions.  Aliasing is a mechanism for
1522
breaking such cycles by ensuring that only one copy of an object is
1523
ever written to disk, or that only one copy is created when reading
1524
from disk.  This is done by associating a unique number as an alias
1525
for the object. 
1526
</P>
1527
<P>
1528
For example, when writing to disk, the first time the object is written
1529
the alias definition is set up.  Consequently the alias number is
1530
written instead of the object it represents.  Similarly when reading
1531
from disk, an alias may be associated with an object when it is read.
1532
When this alias is encountered subsequently it will always refer to
1533
this same object. 
1534
</P>
1535
<P>
1536
The objects on which aliasing can be specified are the 
1537
<A HREF="#InputUnion">union fields</A>.  A union field may be qualified
1538
by one or two hash symbols to signify that objects of that type should
1539
be aliased. 
1540
</P>
1541
<P>
1542
The two hash case is used to indicate that the user wishes to gain
1543
access to the objects during the aliasing mechanism.  In the disk
1544
writing case, the object to be written, <I>x</I> say, is split into
1545
its components using the appropriate <CODE>DECONS_</CODE><I>union_field</I>
1546
construct.  Then the user-defined routine, or macro: 
1547
<PRE>
1548
	ALIAS_<I>union_field</I> ( <I>comp</I>, ...., <I>x</I> ) ;
1549
</PRE>
1550
(where <I>comp</I> ranges over all the union components) is called
1551
prior to writing the object components to disk. 
1552
</P>
1553
<P>
1554
Similarly in the disk reading case, the object being read, <I>x</I>,
1555
is initialised by calling the user-defined routine: 
1556
<PRE>
1557
	UNALIAS_<I>union_field</I> ( <I>x</I> ) ;
1558
</PRE>
1559
prior to reading the object components from disk.  Each object component
1560
is then read into a local variable, <I>comp</I>.  Finally the user-defined
1561
routine: 
1562
<PRE>
1563
	UNIFY_<I>union_field</I> ( <I>comp</I>, ...., <I>x</I> ) ;
1564
</PRE>
1565
(where <I>comp</I> ranges over all the union components) is called
1566
to assign these values to <I>x</I> before returning. 
1567
</P>
1568
<P>
1569
In the single hash case the object is not processed in this way. 
1570
It is just written straight to disk, or has its components immediately
1571
assigned to it when reading from disk. 
1572
</P>
1573
<P>
1574
Note that aliasing is used, not just in the disk reading and writing
1575
routines, but also in the object printing functions.  After calling
1576
any such function the user should call the routine: 
1577
<PRE>
1578
	void clear_<I>name</I>_alias ( void ) ;
1579
</PRE>
1580
to clear all aliases. 
1581
</P>
1582
<P>
1583
Aliases are implemented by adding an extra field to the objects to
1584
be aliased, which contains the alias number, if this has been assigned,
1585
or zero, otherwise.  A list of all these extra fields is maintained.
1586
In addition to the routine <CODE>clear_</CODE><I>name</I>_alias mentioned
1587
above, the user should provide support functions and variables: 
1588
<PRE>
1589
	unsigned int crt_<I>name</I>_alias ;
1590
	void set_<I>name</I>_alias ( <I>name</I> *, unsigned int ) ;
1591
	<I>name</I> *find_<I>name</I>_alias ( unsigned int ) ;
1592
</PRE>
1593
giving the next alias number to be assigned, and routines for adding
1594
an alias to the list of all aliases, and looking up an alias in this
1595
list.  Example implementations of these routines are given in the
1596
<A HREF="#Example"><CODE>calculus</CODE> program</A> itself. 
1597
</P>
1598
 
1599
<H3><A NAME="Application">5.5. Application to calculus</A></H3>
1600
<P>
1601
As <A HREF="#Example">mentioned above</A>, the <CODE>calculus</CODE>
1602
program itself is an example of its own application.  It therefore
1603
contains routines for reading and writing a representation of an algebra
1604
to and from disk, and for pretty-printing the contents of an algebra.
1605
These may be accessed using the <A HREF="#Options">command-line options</A>
1606
mentioned above. 
1607
</P>
1608
<P>
1609
If the <CODE>-w</CODE> command-line option is specified to 
1610
<CODE>calculus</CODE> then it reads its input file, <I>input</I>,
1611
as normal, but writes a disk representation of the input algebra to
1612
<I>output</I>, which in this instance is an output file, rather than
1613
an output directory.  An output file produced in this way can then
1614
be specified as an input file to <CODE>calculus</CODE> if the <CODE>-r</CODE>
1615
option is given.  Finally the input algebra may be pretty-printed
1616
to an output file (or the standard output if no <I>output</I> argument
1617
is given) by specifying the <CODE>-o</CODE> option. 
1618
</P>
1619
 
1620
<HR>
1621
<H2><A NAME="Templates">6. Template files</A></H2>
1622
<P>
1623
It is possible to use <CODE>calculus</CODE> to generate an output
1624
file from a template input file, <I>template</I>, using the syntax:
1625
<PRE>
1626
	calculus [ <I>options</I> ] <I>input</I> .... -T<I>template output</I>
1627
</PRE>
1628
The template file consists of a list of either template directives
1629
or source lines containing escape sequences which are expanded by
1630
<CODE>calculus</CODE>.  Template directive lines are distinguished
1631
by having <CODE>@</CODE> as their first character.  Escape sequences
1632
consist of <CODE>%</CODE> following by one or more characters. 
1633
</P>
1634
<P>
1635
There are two template directives; loops take the form: 
1636
<PRE>
1637
	@loop <I>control</I>
1638
	....
1639
	@end
1640
</PRE>
1641
and conditionals take the form: 
1642
<PRE>
1643
	@if <I>condition</I>
1644
	....
1645
	@else
1646
	....
1647
	@endif
1648
</PRE>
1649
or: 
1650
<PRE>
1651
	@if <I>condition</I>
1652
	....
1653
	@endif
1654
</PRE>
1655
where <CODE>....</CODE> stands for any sequence of template directives
1656
or source lines. 
1657
</P>
1658
<P>
1659
The <I>control</I> statements in a loop can be <CODE>primitive</CODE>,
1660
<CODE>identity</CODE>, <CODE>enum</CODE>, <CODE>struct</CODE> or 
1661
<CODE>union</CODE> to loop over all the primitive, identity, enumeration
1662
structure or union types within the input algebra.  Within an 
1663
<CODE>enum</CODE> loop it is possible to use <CODE>enum.const</CODE>
1664
to loop over all the enumeration constants of the current enumeration
1665
type. Within a <CODE>struct</CODE> loop it is possible to use 
1666
<CODE>struct.comp</CODE> to loop over all the components of the current
1667
structure.  Within a <CODE>union</CODE> loop it is possible to use
1668
<CODE>union.comp</CODE> to loop over all the shared components of
1669
the current union, <CODE>union.field</CODE> to loop over all the fields
1670
of the current union, and <CODE>union.map</CODE> to loop over all
1671
the maps of the current union.  Within a <CODE>union.field</CODE>
1672
loop it is possible to use 
1673
<CODE>union.field.comp</CODE> to loop over all the components of the
1674
current union field.  Within a <CODE>union.map</CODE> loop it is possible
1675
to use 
1676
<CODE>union.map.arg</CODE> to loop over all the arguments of the current
1677
union map. 
1678
</P>
1679
<P>
1680
The valid <I>condition</I> statements in a conditional are <CODE>true</CODE>
1681
and <CODE>false</CODE>, plus <CODE>comp.complex</CODE>, which is true
1682
if the current structure or union field component has a complex type
1683
(i.e. those for which <CODE>COPY_</CODE><I>type</I> and 
1684
<CODE>DEREF_</CODE><I>type</I> require two arguments), and 
1685
<CODE>comp.default</CODE>, which is true if the current structure
1686
or union field component has a default initialiser value. 
1687
</P>
1688
<P>
1689
A number of escape sequences can be used anywhere.  <CODE>%ZX</CODE>
1690
and 
1691
<CODE>%ZV</CODE> give the name and version number of the version of
1692
<CODE>calculus</CODE> used.  <CODE>%Z</CODE> and <CODE>%V</CODE> give
1693
the name and version number of the input algebra.  <CODE>%%</CODE>
1694
and 
1695
<CODE>%@</CODE> give <CODE>%</CODE> and <CODE>@</CODE> respectively,
1696
and 
1697
<CODE>%</CODE> as the last character in a line suppresses the following
1698
newline character. 
1699
</P>
1700
<P>
1701
Within a <CODE>primitive</CODE> loop, <CODE>%PN</CODE> gives the primitive
1702
name, <CODE>%PM</CODE> gives the short primitive name and <CODE>%PD</CODE>
1703
gives the primitive definition. 
1704
</P>
1705
<P>
1706
Within an <CODE>identity</CODE> loop, <CODE>%IN</CODE> gives the identity
1707
name, <CODE>%IM</CODE> gives the short identity name and <CODE>%IT</CODE>
1708
gives the identity definition. 
1709
</P>
1710
<P>
1711
Within an <CODE>enum</CODE> loop, <CODE>%EN</CODE> gives the enumeration
1712
name, <CODE>%EM</CODE> gives the short enumeration name and <CODE>%EO</CODE>
1713
gives the enumeration order, <CODE>ORDER_</CODE><I>enum</I>.  Within
1714
an 
1715
<CODE>enum.const</CODE> loop, <CODE>%ES</CODE> gives the enumeration
1716
constant name and <CODE>%EV</CODE> gives its value. 
1717
</P>
1718
<P>
1719
Within a <CODE>struct</CODE> loop, <CODE>%SN</CODE> gives the structure
1720
name and <CODE>%SM</CODE> gives the short structure name. 
1721
</P>
1722
<P>
1723
Within a <CODE>union</CODE> loop, <CODE>%UN</CODE> gives the union
1724
name, 
1725
<CODE>%UM</CODE> gives the short union name and <CODE>%UO</CODE> gives
1726
the union order, <CODE>ORDER_</CODE><I>union</I>.  Within a 
1727
<CODE>union.field</CODE> loop, <CODE>%FN</CODE> gives the field name.
1728
Within a <CODE>struct.comp</CODE>, <CODE>union.comp</CODE> or 
1729
<CODE>union.field.comp</CODE> loop, <CODE>%CN</CODE> gives the component
1730
name, <CODE>%CT</CODE> gives the component type, <CODE>%CU</CODE>
1731
gives the short form of the component type and <CODE>%CV</CODE> gives
1732
the default component initialiser value (if <CODE>comp.default</CODE>
1733
is true).  Within a <CODE>union.map</CODE> loop, <CODE>%MN</CODE>
1734
gives the map name and <CODE>%MR</CODE> gives the map return type.
1735
Within a 
1736
<CODE>union.map.arg</CODE> loop, <CODE>%AN</CODE> gives the argument
1737
name and <CODE>%AT</CODE> gives the argument type. 
1738
</P>
1739
<P>
1740
As an example, the following template file gives a simple algebra
1741
pretty printer: 
1742
<PRE>
1743
	ALGEBRA %X (%V):
1744
 
1745
	/* PRIMITIVE TYPES */
1746
	@loop primitive
1747
	%PN (%PM) = &quot;%PD&quot; ;
1748
	@end
1749
 
1750
	/* IDENTITY TYPES */
1751
	@loop identity
1752
	%IN (%IM) = %IT ;
1753
	@end
1754
 
1755
	/* ENUMERATION TYPES */
1756
	@loop enum
1757
 
1758
	enum %EN (%EM) = {
1759
	@loop enum.const
1760
		%ES = %EV,
1761
	@end
1762
	} ;
1763
	@end
1764
 
1765
	/* STRUCTURE TYPES */
1766
	@loop struct
1767
 
1768
	struct %SN (%SM) = {
1769
	@loop struct.comp
1770
		%CT %CN ;
1771
	@end
1772
	} ;
1773
	@end
1774
 
1775
	/* UNION TYPES */
1776
	@loop union
1777
 
1778
	union %UN (%UM) = {
1779
	@loop union.comp
1780
		%CT %CN ;
1781
	@end
1782
	} + {
1783
	@loop union.field
1784
		%FN -&gt; {
1785
	@loop union.field.comp
1786
			%CT %CN ;
1787
	@end
1788
		} ;
1789
	@end
1790
	} ;
1791
	@end
1792
</PRE>
1793
</P>
1794
<HR>
1795
<P><I>Part of the <A HREF="../index.html">TenDRA Web</A>.<BR>Crown
1796
Copyright &copy; 1998.</I></P>
1797
</BODY>
1798
</HTML>