Homework 10
Extending Huey, A Language for RGB Values
Due: Thursday, April 25, at 11:59 PM
Introduction
This assignment extends Huey, our little RGB color language, and the interpreter and other tools that process programs written in the language. The new version of the language supports local variables.
Before going any farther, read the updated Huey language specification. It defines the language, in particular the extensions, and talks about some of the Racket you can use to implement your homework.
Code and Files
For this assignment, you will extend the Huey interpreter to handle local variables, including the syntax procedures that define the new expressions, the pre-processor, and the evaluator. You will organize your code in the same way as you did for Homework 9.
Here are a few changes specific to this assignment:
-
Make a copy of the
huey-hw09/
directory from Homework 9, which will contain all your files for the project. Name the copyhuey-hw10/
. Modify and extend these files for the project. -
Put the abstract data type you implement for
Problem 1 in a new file name
datatypes.rkt
. It will contain the datatypes we implement for our language-processing programs. (There will be at least one more datatype soon.) -
Put the
(run-huey)
function you write for Problem 5 in theinterpreter.rkt
file. -
Make sure to update the
provide
clause in each file to include the new public functions you write.
We will extend the Huey language and intepreter again on the next homework assignment. Please comment your source code so that you and I can easily find the pieces relevant to this assignment.
A Data Abstraction for Environments
In order to support local variables, our interpreter needs a way to map names onto values. To provide this behavior, we need an abstract data type called an environment. The environment ADT is an example of a finite function.
This data type consists of four operations:
-
the ability to create an empty set of bindings with
(make-bindings)
, -
the ability to bind a variable to a value with
(bind var val existing-bindings)
, -
the ability to look up the value of a variable with
(look-up var existing-bindings)
, and -
the ability to check whether a variable is defined in an
environment, with
(var-exists? var existing-bindings)
.
The var-exists?
function is an addition to the
interface of finite functions we studied in class. It enables us
to determine whether an environment contains a particular variable,
without ever having to look up a non-existent variable and cause
an error.
Problems
-
Implement the environment ADT as a finite function using
association lists.
An association list is a list of name/value pairs, such as:((foo . 2) (bar . 5) (baz . 15))
For example:> (make-bindings) () > (bind 'foo 2 (make-bindings)) ((foo . 2)) > (bind 'bar 5 (bind 'foo 2 (make-bindings))) ((bar . 5) (foo . 2)) > (define env (bind 'bar 5 (bind 'foo 2 (make-bindings)))) > (look-up 'foo env) 2 > (var-exists? 'bif env) #f > (look-up 'bif env) environment: undefined variable -- baz
You may write your own recursive code to implement thelook-up
function, or you may use the Racket's primitiveassoc
function. -
Define the syntax procedures for variable references and
color/in
expressions.
For each of the new expression types, define a type predicate, a constructor, and the corresponding access procedures.
Be sure to extend the general type predicatehuey-exp?
(or whatever you named it) to recognize the new types of expression, too. -
Extend
(preprocess sugared-exp)
to handle variable references andcolor/in
expressions.
Both of the new types of expression are core features of Huey, sopreprocess
needs only to de-sugar the sub-expressions of a variable declaration: the body and the variable's value.
For example:> (preprocess 'white) 'white > (preprocess '(color purple = ((rgb 255 0 0) mix (rgb 0 0 255)) in (darker purple))) '(color purple = (((rgb 255 0 0) * 0.5) + ((rgb 0 0 255) * 0.5)) in (purple * 0.5)) > (preprocess '(color purple = ((rgb 255 0 0) mix (rgb 0 0 255)) in (color reverse-purple = (invert purple) in (darker reverse-purple)))) '(color purple = (((rgb 255 0 0) * 0.5) + ((rgb 0 0 255) * 0.5)) in (color reverse-purple = (invert purple) in (reverse-purple * 0.5)))
-
Extend
(eval-exp exp)
to handle variable references andcolor/in
expressions.
eval-exp
returns the value ofexp
, which now may be or contain the new kinds of expression, as specified by the language's semantics.
What Racket will display as a result ofeval-exp
depends on how you represent RGB values internally. If you use a representation like thergb
expressions in the language, for example, it might display values such as these:> (eval-exp 'white) '(rgb 255 255 255) > (eval-exp '(color red = (rgb 255 0 0) in (darker red))) '(rgb 127 0 0) > (eval-exp '(color red = (rgb 255 0 0) in (color pink = (white mix red) in (darker pink)))) '(rgb 127 63 63) > (eval-exp 'gray) eval-exp: undefined variable -- gray
eval-exp
must now maintain its own environment and look up the value of a variable references in the environment. Haveeval-exp
do the following:- create an initial environment in which to evaluate its argument. This environment should contain the primitive values of Huey.
- pass the initial environment, along with the pre-processed version of its argument, to the helper function that actually evaluates an expression in a given environment.
color/in
expression creates a new variable, which must be added to the environment before its body is evaluated. The helper will pass the extended environment on its recursive call. -
Define a function
(run-huey)
that opens a REPL for your Huey interpreter.
Have the eval step in your REPL call youreval-exp
function. Feel free to use the ideas from the reading on imperative programming, but customize the REPL so that it is unmistakably yours!
The print step in your REPL should display a color in the following form:R: ___ G: ___ B: ___
Extra credit points will be awarded if the the red, green, and blue components are displayed in the corresponding color!
The read step in your REPL should validate the input before calling the evaluator. If the user enters an illegal expression, that is, anything that is not a legal Huey program, the REPL should not cause an error. Instead, have it write an error message to the screen and let the user enter another expression.
Deliverables
By the due time and date, use the course submission system to submit the following files electronically:
syntax-procs.rkt
interpreter.rkt
datatypes.rkt
tests.rkt
utilities.rkt
(optional)
Be sure that your submission follows the submission requirements. As always, use the specified names for your files. This enables the autograder to find and run your code.