Next: 4 Encapsulation
Up: Differences between Sather-1.0 and
Previous: 2 Main Goals
Sometimes the textual or temporal ordering of language constructs is
important. In general, ordering presents problems because programs
which depend on a particular ordering are usually relying on some
subtle property that would be better if it were explicit. S1 and SK
agree that programs which rely on ordering are often poorly designed,
and writing such programs should be prevented if possible. The best of
all worlds would be to detect reliance on ordering and make it a
compile time error. Unfortunately, doing so does not appear tractible.
In general, the S1 approach has been to avoid harm from ambiguous
orderings by defining a canonical result. More generally, S1 is
deterministic both within and between platforms, with the exception of
converting pointer values to integers for use in hash tables, and code
which exploits the number of bits in INT or CHAR. In general the SK
approach has chosen the traditional approach of not attempting to
rescue the programmer from nondeterminism. However, non-deterministic
semantics may offer more opportunities for optimizing code.
There are a number of places where the handling of ordering creates a
language difference:
- Observed side-effects in shared attribute initialization.
- Issue:
- Both S1 and SK forbid cycles in initialization
expressions but do not define a strong order of evaluation.
Observable side-effects in initialization expressions leads to
constants which differ from one compiler to another.
- Choices:
- S1 restricts shared and const initialization by
recursively defining constant expressions, which forbid
observable side-effects. This make the order of evaluation
irrelevant. SK does not forbid side-effects.
- Value of unassigned variables.
- Issue:
- What should be done with unassigned variables, either
local variables or attributes of objects? Setting them to a
canonical value allows code which implicitly depends on this
value, whereas not defining the value allows code which may run
on one compiler but break on another. General checking for use
of unassigned variables is presumed to be too expensive.
- Choices:
- S1 defines all unassigned variables to have a default
value, which usually amounts to
in the data type. This is desirable for
pointer types for garbage collection and is standard practice
in many collected language implementations. SK does the same
for reference objects, but is not defined for value
objects.
- Observation for S2:
- With good flow analysis, perhaps the use of
unassigned variables could be checked without exorbitant
overhead, and perhaps S2 could distinguish between sentinel
values and unassigned variables.
- Rules for resolving conflict during code inclusion.
- Issue:
- What should be done with multiply-defined class
features? Multiply defined features are either deliberate or a
mistake. The former should be easy to express while the latter
should be a detectable error.
- Choices:
- S1 distinguishes between features textually defined in
a class and those included from another class. Order of
definition and inclusion is irrelevant; features defined in a
class always override those defined out of the class, and
conflicts between features defined out of the class must be
resolved explicitly at a point of inclusion. In SK textual
order of definition is significant; later definitions override
earlier ones. SK made this choice because of its simplicity,
and because an order is required for the structure
expressions, see below and section 4.
- Ordering of attributes.
Similar to the above, SK defines a textual order of object
attributes which is important to the definition of the
structure expression. The structure expression is motivated
by SK's treatment of encapsulation (see
section 4--there is no equivalent in S1.)
- Evaluation of arguments.
- Issue:
- How are routine arguments evaluated? How are out
arguments assigned - what happens when they are aliased? If an
order of evaluation is defined, optimization must operate under
more constraints; if an order is not defined, programs may
break when switching compilers. The quantitative and
qualitative aspects of either choice are not well researched in
the compiler literature nor even in the compiler community
There is
historical precedent for leaving the order undefined.
- Choices:
- S1 defines a canonical left-to-right order of
evaluation of all arguments. SK makes it implementation
dependent. The motivation for this choice is the better
efficiency of the generated code.
- Restrictions on .
- Issue:
- What is permitted in the statement? Historically,
some languages have restricted the target values to be
constants which can be evaluated by the compiler (C ),
but other have defined a sequential semantics (Lisp ).
Restricting it to constants guarantees ordering can't matter.
- Choices:
- S1 defines the case statement as syntactic sugar for
an - - chain. In
multiple expression evaluation, S1 introduces an
auxiliary variable in the definition of .
However, the compiler exploits sequences of constants whenever
they occur. SK requires the targets to be constants.