This
course is an introduction to formal semantic methods for programming
languages. The importance of seeking to define our computer
languages in a formal way is clear. There are two informal
ways to decribe a language, but both have major problems
when it comes to using them as a definition of the language.
The first is simply to decribe, usually through examples,
how the language is meant to be used. This is essential
when teaching the language, but is inadequate as a definition of
the semantics of the language. The other way is to build
a implementation of the language (either a compiler or an
interpreter). The problem with this is that different implementations
can have different results with the same program, depending
on the platform used and the choices of the implementor.
Formal methods are needed to define the language, and also
to guide the implementor to a correct implementation. Without
these methods, we are left with informal descriptions which
can
be ambiguous,
or, worse, inconsistent. Just as we use BNF (plus context-sensitive
additions) to define syntax formally, we need a method to
define semantics just as formally.
That's
where the problems start. Syntax, especially if it is context-free,
merely
needs a simple formal grammar system. Semantics, which has the
job of describing state transitions and other dynamic events
has to be much more complex. There are three main ways to express
formal semantics. Although they are related, they are based on
different formal systems; their mathematical foundations
are different. Axiomatic semantics was developed by Hoare,
and later Floyd to express state transitions through pre-
and post-conditions on program state. Denotational semantics
was developed by Scott and Strachey for expressing the same state
transitions as operations on sets and functions. Lastly,
and most recently, so-called large-step operational semantics
was developed by Plotkin to express state transitions through
logical relationships between the components of the transition.
All three methods tie syntax to semantics formally, and that
is their main goal. All three answer the question "What is the
meaning of a piece of syntax?" (i.e. a source code program),
and all three do it by breaking down a whole program into
its components (i.e. statements. expressions, etc.) It is possible,
by using the techniques inherent in each method, to prove
facts about programs mathematically. This is an important
side-effect of the methods. No longer do we have to execute
a program on a real machine to check results; we can prove them
formally by applying the semantics to the source code. This is
why these methods are so important. |