Certain language constructions which can be cumbersome for the programmer to write can be “contracted” into equivalent forms. The resulting shorter form is called a contraction. The constructions that can be contracted are:
See for example the following collateral declaration of several variables of the same name, followed by it’s corresponding contraction:
int size, int offset, int value := 1024; int size, offset, value := 1024;
In the contracted form above, the same actual declarer
(int
) is shared among all the declared variables. The
elaboration is still collateral, as implied by the comma separator.
The same can be applied to identity declarations. If we turn the variables above into constants, we have:
int size = 0, int offset = 0, int value = 1024; int size = 0, offset = 0, value = 1024;
Note that you cannot mix variable declarations and constant declarations in the same contraction. If you tried to do:
int alignment = 1, int value := 1024; int alignment = 1, value := 1024; # BAD #
The first collateral declaration is perfectly valid, but the resulting
contraction is not. The reason is that in the variable declaration
for value
the mode at the left is an actual declarer that
generates a new name to hold the value, whereas the mode at the left
in the identity declaration for alignment
is a formal declarer.
This becomes more clear if we explicit the generator in the variable
declaration:
int alignment = 1, loc int value := 1024; int alignment = 1, value := 1024; # BAD #
Identity declarations of routines can become clunky:
proc([]real,real)real waverage = ([]real numbers, real weight) real: begin ... end
The corresponding contracted form, where the actual declarer is
shortened to proc
, would be:
proc waverage = ([]real numbers, real weight) real: begin ... end
Note however that the contraction form of a routine declaration is less expressive than the uncontracted form. In the contracted form it is required for the right hand side to be a routine text. That is not the case in the uncontracted form, in which the right hand side can be any unit yielding a routine of the expected mode, like in:
proc(int,int) transformer = (op = add | int(int a, int b)int: a + b | int(int a, int b)int: a * b);
Finally, collateral declarations of the priority of operators can also be contracted in the expected way:
prio isoneof = 6, prio ismanyof = 6; prio isoneof = 6, ismanyof = 6;
Simplified [RR 4.1.1.b:c]:
b) COMMON joined definition of PROPS: COMMON joined definition of PROPS, and also token, joined definition of PROP. c) COMMON joined definition of PROP: COMMON definition of PROP.
Note that and also token
is the comma symbol in most
representations.
The rules above are used in the syntax of all the constructs mentioned in this article. For example the following simplified rule [RR 4.3.1.a] implements priority declarations:
a) priority declaration of DECS: priority token, priority joined definition of DECS.
Where priority
plays the role of COMMON
and DECS
of PROPS
. The rules for the other constructions are built the
same way, so we are not including them here.