A serial clause contains one or more units. Of these, the units preceding a completer and the unit appearing last in the clause yield a value which in turn will be the value yielded by the complete serial clause.
Consider the following example:
begin int tmp := a; a := b; if tmp = 0 then divbyzero fi; a / temp exit divbyzero: 0 end
This particular serial clause contains one declaration, one label and four units.
The units a / tmp, which appears right before a completer, and
and 0, which is the unit appearing last in the serial clause,
yield an integral value which is the result of the serial clause.
These are called int-units or, more generally,
mode-units. These are also known as expressions.
On the other hand the units a := b and if tmp = 0
then divbyzero fi also yield values. For example, the
assignation yields a of mode ref int. However,
the value yielded by these units gets voided and discarded.
These are void-units, also known as statements.
Simplified [RR 3.2.1.b]:
b) SOID series with PROPSETY:
strong void unit, go on token, SOID series with PROPSETY ;
where (PROPSETY) is (DECS DECSETY LABSETY),
declaration of DECS, go on token,
SOID series with DECSETY LABSETY ;
where (PROPSETY) is (LAB LABSETY),
label definition of LAB,
SOID series with LABSETY ;
where (PROPSETY) is (LAB LABSETY) and SOID balances SOID1 and SOID2,
SOID1 unit, completion token, label definition of LAB,
SOID2 series with LABSETY ;
where (PROPSETY) is (EMPTY),
SOID unit.
In the hyper-rule above the first alternative matches a
void-unit. Note that the unit is in a strong context with
goal mode void, and therefore is subject to voiding.