Due date: 9/30 @ at the beginning of class
The goal of this problem set is to understand reduction relations in
the spirit of chapter I.1 of the Redex book, both in theory and in
practice. The latter continues the introduction to systematic program
design.
Finger Problems:
Solve exercises 1.2, 1.4, and 1.6.
Problem:
A famous characterization of APIs (application programming interfaces) is
that they are languages waiting to be liberated. In this exercise, we deal
with one of these APIs, the language of stacks.
Here is a sketch of a stack API's syntax and its integration with some
expression language:
S is one of:
-- mtS
-- push(S,e)
-- pop(S)
e is one of:
-- a number n
-- add1(e)
-- depth(S)
-- top(S)
The interpretation is the usual one:
mtS
is the empty stack;
push
places a number n
onto an existing stack S
;
top
retrieves the last element that was pushed;
pop
retrieves the last stack onto which an element was pushed;
and depth
determines how many elements the stack contains.
You may imagine that add1(e) is a placeholder for more complex
forms of expressions.
Tasks
-
Develop a metalanguage representation for the stack language.
-
Design a metafunction that counts the number of occurrences of
push in a stack expression.
-
Design a metafunction that replaces all occurrences of numbers
in a stack expression with 0.
-
Design the metafunction evalS. The function maps stack
expressions to normalized stack expressions. This task demands that
you extend the stack language with a language of normalized stacks:
nS is one of:
-- mtS
-- push(nS,n)
-
Develop a basic notion of reduction R for the stack expression
language. The notion of reduction should interpret all operations in the
specified manner.
This task demands that you extend the stack language with a collection of
S contexts.
Implement your model in Redex via a language and a reduction system.
-
Notions of reductions are relations. In contrast to a function, a relation
pairs up several "results" with a given "input". If this is true for your
notion of reduction for the stack language, create an expression that has
at least two paths to a normalized stack using a traces expression.
-
As the book explains, even relations can be used to define a mathematical
evaluation function. Design the metafunction eval->, which
uses your notion of reduction to map stack expressions to normalized stack
expressions.
-
At this point you may conjecture that eval-> and
evalS will always produce the same result when given the same
stack expression.
Formulate this conjecture with redex-check. Borrow
equal? from Racket to compare terms. Report the counter-example
that it finds via a failing test case at the bottom of your file.
Finally make a suggestion as to how to eliminate the problem that
redex-check found.