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:

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:

Problems

  1. 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.

  2. 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 predicate color? (or whatever you named it) to recognize the new types of expression, too.

  3. Extend (preprocess sugared-exp) to handle do expressions.
    This expression is a core feature of Huey, so preprocess needs only de-sugar the sub-expressions of the do and then create a new do 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, so preprocess will not have a case for them. The case for preprocessing do expressions can call a helper function to preprocess the assignment statements it contains.

  4. 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 and black 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.
    After this step, our evaluator should work exactly as it did after Homework 11, even though the environment now maps variables to cells that hold values. All the same tests should pass. We should not notice any changes!

  5. Extend (eval-exp exp) to handle do expressions.
    eval-exp returns the value of exp, 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 of eval-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, so eval-exp will not have a case for them. The case for evaluating do expressions can call a helper function to evaluate the assignment 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.

  1. 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 to run-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))
    

  2. 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 function run-huey-with-state that creates a REPL with top-level variables.
    Users should be able to define 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)
    

  3. 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 named lighter would be a useful bit of sugar in tandem with darker. 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:

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.