Definition Table
The definition table module embodies the concept of a set of
distinguishable entities, each having some set of properties.
There is at least one entity, the invalid entity;
it has an empty set of properties.
No other entities exist unless they are explicitly created.
Nothing is assumed about entities, other than the fact that they are
distinguishable.
Each distinct entity is represented by a distinct key.
The module exports a key representing the invalid entity, and
an operation that creates a new key each time it is invoked.
Properties are declared by the user.
Each property declaration specifies the type of data item that defines the
property, but does not associate the property with any specific entity or
entities.
Query and update operations are used to associate property values with
entities.
Each query or update operation is defined for a single property, and
an invocation associates a single value of the declared type
with the entity to which the operation is applied.
To make the definition table module accessible to a program,
include the header file `deftbl.h' in that program.
Definition table keys are objects of type DefTableKey .
DefTableKey is a private type of the definition table module:
Clients of the definition table module may declare variables and parameters
of type DefTableKey , but they must make no assumptions about its
representation.
The invalid key is NoKey , a legal value of type DefTableKey .
No property values are ever associated with NoKey .
NewKey is a parameterless function that yields a value of type
DefTableKey each time it is invoked.
All of these values are distinct from each other and from NoKey .
Any client of the definition table module may invoke NewKey .
Definition table keys are often bound to identifiers via the
environment module operation DefineIdn
(see Contour-Model Environment Module of Library Reference Manual).
In this case DefineIdn will invoke NewKey if necessary;
NewKey should be invoked directly only for entities that
are not under control of the environment module.
It is sometimes useful to be able to get a new key that is just like an
existing one. The CloneKey
operation takes a single key as argument, uses NewKey to get a
new one, and initialises the properties of the new key to be the same as
those of the key argument. The new key is returned.
Note that CloneKey implements shallow-copying of property values.
For example, if a property value of the key argument is a pointer then
after the CloneKey call two keys will have properties pointing to
the same data.
Each property has a name and a type.
A property type is denoted by a C identifier (a sequence of letters,
digits and underscores that does not begin with a digit).
Property types must either be built-in types of C (such as int ),
or they must be declared via typedef in some accessible module.
The definition table module then becomes a client of the module defining
the property type.
A property name is also denoted by a C identifier.
Property names must be unique, and must be declared in a file of type
.pdl .
The simplest form of declaration is:
Name: Type;
Here Name is the property name being declared and Type is the
data type of the possible values for that property.
Any type that can be returned by a function can be used as the type of a
property.
If the type is declared via typedef , some .pdl file must
contain a C string (sequence of characters delimited by " characters)
that specifies the name of the file containing that declaration.
Each declared property has a basic query operation.
If the name declared for the property is Name , then the
basic query operation is a function named GetName .
If property Name has been declared to have values of type
Type , then the function implementing the basic query
operation has the following prototype:
Type GetName(DefTableKey key, Type deflt)
If GetName is applied to a definition table key with which a value
of the Name property has been associated,
then GetName returns the associated value.
Otherwise it returns the value of parameter deflt .
Since NoKey represents an invalid entity that never has associated
property values, applying any basic query operation to NoKey
will yield the value of parameter deflt .
Each declared property is has two basic update operations.
If the name declared for the property is Name , then the
basic update operations are functions named SetName
and ResetName .
If property Name has been declared to have values of type
Type , then the functions implementing the basic update
operations have the following prototypes:
void SetName(DefTableKey key, Type add, Type replace)
void ResetName(DefTableKey key, Type val)
If SetName is applied to a definition table key with which a value
of the Name property has been associated, then that value is
replaced by the value of parameter replace .
Otherwise the value of parameter add becomes the value of the
Name property associated with that definition table key.
Application of ResetName to a definition table key always
results in the value of the Name property being set to val .
Since NoKey represents an invalid entity that has no associated
property values, applying any basic update operation to NoKey
has no effect.
Defining occurrences of identifiers are the points at which those
identifiers are declared, while applied occurrences are points at
which they are used.
In many programming languages, it is possible to distinguish defining
occurrences from applied occurrences on the basis of context.
Let us assume that this is the case, and use the definition table to verify
that each identifier has exactly one defining occurrence.
The environment module is used to implement the scope rules of the
language, binding a definition table key to each occurrence of an identifier.
Within each individual scope, the same key will be bound to all
occurrences of a particular identifier.
To verify that there is a single defining occurrence,
associate a property Def with the definition table key.
Def is of type integer, and three values are significant:
0
- There is no defining occurrence
1
- There is exactly one defining occurrence
2
- There is more than one defining occurrence
At each defining occurrence, the update operation SetDef is invoked
with the add parameter 1 and the replace parameter
2 .
After all defining occurrences are processed, the Def property value
1 will be associated with the definition table key for each
identifier having exactly one defining occurrence.
The Def property value 2 will be associated with the
definition table key for each identifier having more than one defining
occurrence, and there won't be any Def property value associated
with the definition table key for each identifier without defining
occurrences.
At each applied occurrence, the query operation GetDef is invoked
with the deflt parameter 0 .
If the identifier has one or more defining occurrences, GetDef will
yield the Def property value (either 1 or 2 )
associated with the definition table key for the applied occurrence.
Otherwise there will be no Def property value associated with the
definition table key for the applied occurrence, and GetDef will
yield the value of the deflt parameter: 0 .
|