Turn in two separate files for this assignment: one
containing your code (called hwk2.scm) and the other containing your
tests (called tests.scm). The quality of your test suite is worth a
significant portion of your grade. Write your tests using the
test and test/exn functions in the PLAI
language levels. I will run your tests against each other's code: you
get points for bugs you find in others' code and lose points for bugs
that others' tests find in your code. Due to this, pay attention to
the concrete syntax and function contracts, as mistakes in these would
cause your work to fail against others' test suites.
For consistency of testing for errors using test/exn
(when I cross run your test suites), make sure your error messages
include the following phrase for each kind of error:
Extend the parser and interpreter for the F1WAE language discussed in class (and the text) with the language features described below. The text can be of great assistance in this part of the assignment; it provides the beginnings of a parser, an abstract syntax datatype and an interpreter. Your interpreter should have eager application semantics.
As part of the assignment, implement the function
parse, which consumes an expression in the
language’s concrete syntax and returns the abstract syntax
representation of that expression, as well as the function
interp, which consumes an abstract syntax expression (as
returned by the parse function) and returns a
(Scheme) number. Include a contract for every function.
In place of having separate abstract syntax forms for
+ and -, define a single form for all binary
arithmetic operators. Parse these into a binop datatype
variant that includes a symbol for the operation to perform as well as
the two arguments. Define a table that maps operator names (symbols)
to actual functions (Scheme procedures) that perform the corresponding
operation. Having a single form like this, accompanied by a table,
makes your language easier to extend: once you have modified your
parser and interpreter once to support binary operators, you won't
need to touch either one to add any number of new ones. To
demonstrate this, define multiplication and division (using
* and / to represent them in the language's
concrete syntax).
with This feature lets you introduce multiple identifiers in a
single with statement. Each identifier bound by the
with expression is bound only in the body of the
with. Zero or more identifiers can be bound by each
with expression. If there are multiple bindings of the
same identifier in a single with expression’s
bindings list, your interpreter should halt with an error message. An
example:
{with {{x 2}
{y 3}}
{with {{z {+ x y}}}
{+ x z}}
will evaluate to 7, while
{with {{x 2}
{x 3}}
{+ x 2}}
will halt with an error message.
To save the trouble of having to add boolean values and
operators over them, create a restricted conditional construct
if0 with syntax
{if0 F1WAE F1WAE F1WAE}
An if0 expression has three parts:
Evaluation should signal an error for non-numeric test values.