The reason we are studying algebras, which are just sets with some functions among them, is to use them for the denotations of programs in programming languages. In fact, we will also have "carriers" (i.e., sets) for the various syntactic categories of a language (expression, statement, declaration, block, etc.), and the denotation function will be one of the functions in the algebra. Since this algebra will be defined using the OBJ language, we can actually execute all of our definitions, and in particular, we can execute programs, we can play with the semantics, we can define new features, etc., all without a compiler, an interpreter, or even a parser for the language. Signatures are just the syntax of the algebra, so things like the symbol for the denotation function will be in the signatures of our semantic algebras for programming.

**1.1** To be a bit more precise, an OBJ3 signature can be considered a
variant notation for a context free grammar, with some additions like
precedence and subsort polymorphism, and more importantly, with an
implementation, which is the very general parsing mechanism in OBJ3; this
provides a general and powerful way to handle syntax (we will later see that
OBJ also provides powerful ways to handle semantics). The sorts of a
signature correspond to the non-terminals of a grammar. OBJ3's subsort
polymorphism provides a highly consistent treatment of the most common kinds
of coercion, in a way that also supports the most common kind of overloaded
operations. This is in contrast to the coercion mess found in many
programming languages, and it is very convenient for defining denotations.

The prefix notation defined in `NAT`

is called **Peano
notation**, of which "tally notation," also called "jailbird" or "prison
notationm" is a variant (one is `|`, two is `||`, three is
`|||`, etc.); some example terms appear on pages 18 and 19 (though
strictly speaking these use a larger signature). There is a bug in Figure 1.2
on page 14: the sort should be `Exp`

instead of `Nat`

.

**1.2** A *semantics* for a signature is given by an algebra
*A* for that signature. Such an algebra gives a denotation for each sort
*s*, which is the set *A _{s}* of elements of

**1.3** The operations in the term algebra of a signature are
*exactly* the *constructors* (in the sense of abstract syntax)
for the abstract syntax of the context free language defined by that
signature. Moreover, the carrier of sort *s* of the term algebra
consists of exactly the abstract syntax trees (expressed as terms) for the
grammar of that sort. Neat!

To be more precise, suppose that *G = (N,T,P,S)* is a context free
grammar. Then the signature for *G*, denoted *Sigma ^{G}*,
has as its sort set

*p: N ->
w _{1} N_{1} w_{2} N_{2} ... w_{n}
N_{n} w_{n+1} *

is a production in *P* with each *N _{i}* a non-terminal,
and each

*p:
N _{1} N_{2} ... N_{n} -> N *

and the *Sigma ^{G}*-term algebra is exactly the algebra of
abstract syntax terms (or trees) for

We can use the above construction plus the function phi-bar on page 21,
with *Sigma ^{G}* as its source and a suitable semantic algebra

`A`

as its target to get a very nice explanation of synthesized
attribute semantics. For example, if `G`

is the simple grammar for
expressions discussed in the notes on chapter 2 of
Sethi (with sort `E`

but without sort `S`

), we can
let `A`

be the integers, and define the various operations to be
just the usual operations on integers (i.e., 0 is zero, 1 is one, + is
addition, * is times). Then the unique homomorphism phi-bar computes the
value of the expression. If a given non-terminal has more than one
attributes, then the carrier in `A`

will have to be a product of
the sets of values for each attributes, but otherwise things work just the
same way.
**1.4** The notion of *assignment* in Definition 9 is essentially
the same as in Stansifer on page 67, but much more general.

**1.6** In Definition 14 on page 30, on the first line,
*(T _{Sigma}U Xi)_{s}* should instead be

The rule [SM] on page 31 should be

(s X)* Y = (X * Y)+ Y .

**1.6.1** There is a bug on page 35: in the equation

eq head(N L) = I .the variable

`I`

should have been `N`

. (Thanks for
Monica Marcus for noticing this.)
**1.6.3** The last line of the definition of `NATEXPEQ`

on
page 39 should be

eq (s X)* Y = (X * Y)+ Y .(Thanks to Bob Boyer, CSE 230 W'01.) Moreover, the same typo occurs in the rule [SM] on page 31.

The "Theorem of Constants" is really a justification for the universal quantifier elimination rule:

- To prove an equation (forall X)e over a signature Sig, it suffices to prove e over Sig(X).

- A |-
_{Sig(X)}P implies A |-_{Sig}(forall X) P

There is, however, an important caveat regarding use of the disequality predicate (see Section 2.1.1). For example, suppose we are trying to prove a first order formula (forall X,Y) P(X,Y) over Sig, and use the Theorem of Constants to reduce it to proving P(x,y) over Sig(x,y). Because x=/=y (since they are distinct constants), what we have really proved is

- (forall X,Y) X=/=Y implies P(X,Y) .

But what should be done if the proof does use x=/=y? We can complete the proof by proving P(x,x), which then gives (forall X) P(X,X). This can be justified by considering the two proofs as parts of a case analysis, where the two cases are X=/=Y and X=Y.

Some important ideas are introduced in the problems of this chapter,
especially the notion of **homomorphism** (on page 48), which allows one
to explain why "initial algebras" are so called: it is because they can be
characterized as exactly those algebras that have exactly one homomorphism
to each other algebra in the same class of algebras.

To CSE 230 homepage

To CSE 230 notes page

Maintained by Joseph Goguen

© 2000, 2001, 2002, 2003 Joseph Goguen

Last modified: Fri Feb 21 10:56:04 PST 2003