Homework 11
Adding State to Huey, A Language for RGB Values
Due: Friday, May 3, at 11:59 PM
Introduction
For this assignment, we extend Huey, our RGB color language, one last time. You will modify the interpreter and other tools that process Huey programs so that they support assignment statements.
Before going any farther, read the updated Huey language specification, especially the sections marked new. These sections define the new features being added to the language.
Then, read this outline for adding features to a language and its processors. The instructions below include all the requirements for the assignment, but they assume that you are comfortable with adding new features to our language and interpreter. The reading walks through the process we have used before to extend a language, offering more explicit instructions and hints for implementation, including some Racket you might want to use.
Code and Files
For this assignment, you will extend the Huey interpreter to handle
do
-blocks with assignment statements, 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
Homework 10.
Here are a few changes specific to this assignment:
-
Make a copy of the
huey-hw10/
directory from Homework 10, which will contain all your files for the project. Name the copyhuey-hw11/
. Modify and extend these files for the project. -
Put the abstract data type you implement for
Problem 1 in your
datatypes.rkt
file. It will now contain two datatypes. -
Make sure to update the
provide
clause in each file to include the new public functions you write. Don't include helpers that you create as a part of organizing your code.
Please comment your source code so that you and I can easily find the various pieces.
A Data Abstraction for Cells
In order to support mutable variables, our interpreter must map names not to values but to locations that hold values. To provide this behavior, we need an abstract data type called a cell. The cell ADT is an example of a mutable object. We explored several alternative implementations for mutable objects in Sessions 24 and 25.
The interface of the cell ADT consists of three operations:
-
(cell init-value)
, which creates a new cell containinginit-value
-
(cell-value a-cell)
, which returns the value of the cell -
(cell-set! a-cell new-value)
, which changes the value of the cell tonew-value
Problems
-
Implement the cell ADT as a pair of procedures that share
data.
For example:
> (define foo (cell 0)) > (cell-value foo) 0 > (cell-set! foo 10) 10 > (cell-value foo) 10 > (cell-set! foo (+ (cell-value foo) 5)) 15 > (cell-value foo) 15
You may implement the cell using any of the techniques we learned in class, as long as the cell is a pair (cons
) of procedures. -
Define the syntax procedures for
do
expressions and for the assignment statements they contain.
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 predicatecolor?
(or whatever you named it) to recognize the new types of expression, too. -
Extend
(preprocess sugared-exp)
to handledo
expressions.
This expression is a core feature of Huey, sopreprocess
needs only de-sugar the sub-expressions of thedo
and then create a newdo
expression.
For example:> (preprocess '(do (darker (rgb 255 0 0)))) '(do ((rgb 255 0 0) * 0.5)) > (preprocess '(color c = (rgb 0 255 0) in (do (c <= (c mix (rgb 0 0 255))) (c <= (invert c)) (darker (c shift 5))))) '(color c = (rgb 0 255 0) in (do (c <= ((c * 0.5) + ((rgb 0 0 255) * 0.5))) (c <= (invert c)) ((c shift 5) * 0.5)))
Note:assignment
statements are not legal Huey expressions, sopreprocess
will not have a case for them. The case for preprocessingdo
expressions can call a helper function to preprocess theassignment
statements it contains. -
Modify the evaluator's environment to map variables to cells
that contain values, not values.
Use the cell ADT you implemented for Problem 1.
This requires three changes:-
change the initial environment to bind
white
andblack
to cells that hold their values, - change the part of the evaluator that extends an environment to bind the new variable to a cell that holds its value, and
- change the part of the evaluator that looks up the value of a variable in the environment to ask the cell it finds for the actual value.
-
change the initial environment to bind
-
Extend
(eval-exp exp)
to handledo
expressions.
eval-exp
returns the value ofexp
, which now may be or contain the new kind of expression, as specified by the language's semantics.
What Racket will display as a result ofeval-exp
still depends on how you represent RGB values internally. If you use lists of size three, for example, it might display values such as these:> (eval-exp 'white) '(255 255 255) > (eval-exp '(do (rgb 255 0 0))) '(255 0 0) > (eval-exp '(color c = (rgb 0 255 0) in (do (c <= (c mix (rgb 0 0 255))) (c <= (invert c)) (darker (c shift 5))))) '(127 66 66) > (eval-exp '(color c = (rgb 0 255 0) in (color d = (rgb 0 0 255) in (do (c <= (c mix d)) (d <= (c mix d)) ((c mix d) shift 5))))) '(5 99 163) > (eval-exp '(color c = (rgb 0 255 0) in (do (c <= (invert d)) ;; notice the 'd' c))) eval-exp: undefined variable d
Note again:assignment
statements are not legal Huey expressions, soeval-exp
will not have a case for them. The case for evaluatingdo
expressions can call a helper function to evaluate theassignment
statements it contains.
For each assignment statement, the helper updates the value of the variable in the current environment. It does not add a new variable to the environment.
Extra Credit Opportunities
If you finish the above tasks and would like the chance to earn a
few extra points, try one or more of these exercises. If you do,
be sure to document your attempt clearly in the header
block of your interpreter.rkt
file.
-
Modify the REPL with an option to print colors in hex format.
After we create a useful color, we might want to use it in the CSS file for a website. Huey could display colors in hex format in order to make that easier.
One way to support this would be to let the user toggle the display format with a REPL command:huey! > (hex on) huey! > (rgb 255 0 0) "#ff0000" huey! > ((black mix (rgb 255 0 0)) mix white) "#be7f7f" huey! > (hex off) huey! > (rgb 255 0 0) (255 0 0)
Another option would be to make this an option when we create the REPL, say, by passing a flag as an argument torun-huey
.> (run-huey 'hex) huey! > (rgb 255 0 0) "#ff0000" huey! > ((black mix (rgb 255 0 0)) mix white) "#be7f7f"
If you want to offer even more flexibility, let the user pass any display function as an argument to a REPL generator.(define run-huey (make-repl display-hex))
-
The Huey REPL that we
implemented enables us to evaluate programs that have state, but
only in
do
expressions within our programs. As currently implemented, the REPL itself does not allow us to enter sequences of stateful expressions at the prompt.
Write a functionrun-huey-with-state
that creates a REPL with top-level variables.
Users should be able todefine
a variable and then use and change it in subsequent expressions, using assignment statements at the top level:huey! > (define c <= (white mix black)) '(127 127 127) huey! > (c <= (c shift 1)) huey! > c '(128 128 128)
-
Define two or more new operators that are syntactic
abstractions.
We have a preprocessor, so adding syntactic abstractions to Huey should be straightforward!
Update Huey's syntax procedures to recognize your new operators, and then modify the preprocessor to translate them into core Huey syntax.
Offhand, I think adding a unary operator namedlighter
would be a useful bit of sugar in tandem withdarker
. Can you think of other combinations of core Huey operations that would be useful shorthand when describing colors?
Run your ideas by me before implementing them. That way, we can make sure that they are valid abstractions and that they are worth extra credit points.
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.