| |
Purpose: | |
|
In this phase we complete the construction of the calculator language interpreter
by adding a handful of key features and upgrading its data types. What has the language been missing? What keeps us from writing useful programs in it? The answer is simple:
Without conditional evaluation, our language can't really be said to be a programming language. It is just a simple macro-expression language. With it, though, it becomes the real thing. (An argument has been made that what really distinguished ENIAC from its predecessors, what made it a computer, rather than a calculator, was the fact that it had a conditional branch instruction.) In this phase we will add conditional evaluation, sequencing, a print statement, and, to round things out, strings as a data type.
| |
Strings as a Datatype | |
The lowest level change to the language involves the incorporation of strings as a
datatype. To this end, the datatype ConcreteSyntax.number has
been replaced with ConcreteSyntax.literal, with three constructors:
Int, Real, and String. Similarly, the
Number constructor has been replaced with Literal,
and all the functions in ConcreteSyntax have been appropriately
renamed and modified. Note that when ConcreteSyntax.literal_to_string
converts a String literal, it includes double quotes around the
underlying string to make the type clear.
In order to incorporate this change into the inerpreter, you will need to
make various changes in
| |
Write and Newline | |
You must add a new unary operator write defined at all object types.
(By object type I mean types in the object language, the
one we are implementing, as opposed to the types of the meta language
we are using for the implementation.)
When printing strings, do not include quotes around the string. To allow for full
generality, the write operator should leave the cursor at the end of
the output, and not advance to the next line. Therefore, you should also
define the zero-ary operator newline.
The write operator should return as its value whatever it is given as
its argument, while the newline operator should return the empty String
literal.
While we could require
| |
Conditonal Evaluation | |
|
In eager languages, conditional evaluation is what is known as a special form.
That is, while it will look just like the other built-in operators from a syntactic
standpoint, it will require a different operational behavior. Unlike the ordinary
built-in operators, this one does not necessarilly evaluate all of its arguments.
Instead a prescribed procedure is used to determine which arguments are actually evaluated.
The form of conditional evaluation we will include in the language is the
The operational semantics (i.e. what the system does when it encounters this
expression) are as follows: Evaluate the first element of the first argument pair.
If that expression evaluates to a non-zero value (as outlined below) then evaluate the
second expression in the pair and return its value as the value of the conditional expression.
If, on the other hand, the first expression evaluates to zero (as outlined below) then the second
expression in the pair is discarded unevaluated, and the process repeats with the next pair.
If the last pair is reached and none of the pairs has a test expression that evaluates non-zero
then the value of the whole conditional expression is
Note that the test expressions can be of any type, so we must have a suitable notion of
"zero" at each object type. Therefore we will assume that the following are all "zero" for the
purposes of deciding whether to evaluate the other expression in the pair:
In order to distinguish this structure from an ordinary application, a new
case has been added to the definition of the datatype
You must modify SyntaxConverter to recognize cond expressions
and convert them to this special form. Then add the appropriate code for evaluating
them to Evaluator.evaluate_cexpression. Note that
AbstractSyntax.cexpression_to_string has already been updated to recognize them.
| |
Relational Operators | |
In order to make the conditional statement useful, you need some test expressions.
To that end, you should support the following relational operators:
<, <=, >, >=, =,
<>. Values of the two numeric types should be able to be compared to one another,
but strings can only be compared to other strings. (String comparison should just be based on the
underlying string comparison function from ML.) Whatever the types of the arguments,
the operators should return (Int 1) if the test is true, and (Int 0)
if it is false.
Note, these are just ordinary built-in operators. They are not new special forms.
Also, we are not saying these are the only operators that can be used to construct test
expressions. Any expression can be used as the first expression in a
(In later projects we will change our notion of "true" and "false" as our data types
get richer. Therefore, you may find it useful to define
| |
Sequencing | |
|
As shown above, with the addition of side effects to the language, it is natural to add
a notion of sequencing.
Strictly speaking it is not necessary to add a new special form for this to the
language, since function application can be used to accomplish the desired efects.
For example, if we knew that the arguments to a function were always evaluated left
to right, we could define the (defun (writeln_aux foo bar) bar) Even if we did not know the order of evaluation of function arguments, eager evaluation imparts an ordering to nested applications. So, we could define it as: (defun (writeln_aux foo) (newline)) Nevertheless, to avoid such machinations, it is useful to add a syntax for sequencing to the language, and to implement it as a special form. The syntax you are to support is:
This syntax should be mapped (in
and evaluated in the way they are in ML. That is, a sequence should evaluate
each of the individual expressions in order, and return the value of the last
expression as the value of the sequence.
| |
What You Should Turn In | |
Only the evaluator and the syntax converter get appreciable changes in this
phase. Therefore, you should submit a single file with the functors
SyntaxConverterFun and EvaluatorFun. They will be linked
with the interpreter from the sample solution to the last phase.
| |
This page copyright ©1998 by Joshua S. Hodas. It was built on a Macintosh. Last rebuilt on Fri, Apr 9, 1999 at 3:10 PM. | |
http://cs.hmc.edu/~hodas/courses/cs131/projects/project06.html | |