Professional Documents
Culture Documents
Introduction
1.1
1.2
Life of a Program
2.1
2.3
Values
Java generics (a polymorphism mechanism) do not support primitive types like int, so in some sense those primitives are secondclass in Java and should be specified in a separate domain from
Object and its subclasses, which are first-class. In Scheme and
C++, procedures (functions) and methods are first-class because all
of the above properties hold. Java methods are not first-class, so
that language contains a Method class that describes a method and
acts as a proxy for it.
The value domain can be specified using set notation, e.g.,
real
complex
number
Expressions
A parser converts the token stream into a parse tree of expressions. The legal expressions are described by the expression
domain of the language, which is often specified in BNF. The
nodes of a parse tree are instances of expressions (e.g., a FOR
node, a CLASS-DEFINITION node) and their children are the subexpressions. The structure of the parse tree visually resembles the
indenting in the source code. Figure 2.2 shows a parse tree for the
expressions found in the token stream from figure 2.1.
int decimal
real real
real complex
2.4
2.2
=
=
=
Implementation Issues
A compiler is a program that translates other programs in a highlevel language to the machine language of a specific computer. The
result is sometimes called a native binary because it is in the native language of the computer2 . An interpreter is a program that
2 Although in practice, most modern processors actually emulate their
published interface using a different set of operations and registers. This
allows them include new architectural optimizations without changing the
public interface, for compatibility.
Syntax
4.1
Backus-Naur Form
Backus-Naur Form (BNF) is a formal way of describing contextfree grammars for formal languages. A grammar is context-free
when the the grammar is consistent throughout the entire language
(i.e., the rules dont change based on context). BNF was first used
to specify the ALGOL programming language.
A BNF grammar contains a series of rules (also known as productions). These are patterns that legal programs in the specified
language must follow. The patterns are typically recursive. In the
BNF syntax, the nonterminal being defined is enclosed in angular
brackets, followed by the ::= operator, followed by an expression
pattern. The expression pattern contains other nonterminals, terminals enclosed in quotation marks, and the vertical-bar operator |
that indicates a choice between two patterns. For example,
hdigiti
hdigitsi
::=
::=
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
hdigiti | hdigitihdigitsi
::=
::=
#t | #f
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
hintegeri
::=
[+|-]hdigiti+
hrationali
::=
hintegeri/hdigiti+
Backus-Naur Form (BNF) formal grammars are a way of describing syntax using recursive patterns
hdecimali
hreali
::=
::=
[+|-]hdigiti . hdigiti+
hintegeri | hrationali | hdecimali
4.2
Syntactic Sugar
incr }
FOR therefore does not add expressivity to the language and is syntactic sugar. In Scheme, LET adds no power over LAMBDA, and
LET* adds no power over LET. Java exceptions are an example of
an expressive form that cannot be eliminated without completely
rewriting programs in the language.
Computability
5.1
(1)
(2)
Let the Halting Function H(P, x) be the function that, given a program P and an input x to P, has value halts if P(x) would halt
(terminate in finite time) were it to be run, and has value does not
halt otherwise (i.e., if P(x) would run infinitely, if run). The Halting Problem is that of solving H; Turing [Tur36] proved in 1936
that H is undecidable in general.
Theorem 1. H(P, x) is undecidable.
At the beginning of the 20th century, mathematicians widely believed that all true theorems could be reduced to a small set of axioms. The assumption was that mathematics was sufficiently powerful to prove all true theorems. Hilberts program3 was to actually
reduce the different fields of mathematics to a small and consistent
set of axioms, thus putting them all on a solid and universal foundation.
5.2
Proof. Assume program Q(P, x) computes H (somehow). Construct another program D(P) such that
D(P):
if Q(P, P) = halts then loop
else halt
In other words, D(P) exhibits the opposite halting behavior of
P(P).
Now, consider the effect of executing D(D). According to the
program definition, D(D) must halt if D(D) would run forever,
and D(D) must run forever if D(D) would halt. Because D(D)
cannot both halt and run forever, this is a contradiction. Therefore
the assumption that Q computes H is false. We made no further
assumption beyond H being decidable, therefore H must be undecidable.
The proof only holds when H must determine the status of every
program and every input. It is possible to prove that a specific program with a specific input halts. For a sufficiently limited language,
it is possible to solve the Halting Problem. For example, every finite
program in a language without recursion or iteration must halt.
The theorem and proof can be extended to most observable properties of programs. For example, within the same structure one
can prove that it is undecidable whether a program prints output or
reaches a specific line in execution. Note that it is critical to the
proof that Q(P, x) does not actually run P; instead, it must decide
what behavior P would exhibit, were it to be run, presumably by
examining the source code of P. See http://www.cgl.uwaterloo.ca/ csk/halt/
for a nice explanation of the Halting Problem using the C programming language.
References