8.10

Homework 10b

home work!

Programming Language #lang htdp/isl+

MUST BE DONE WITH YOUR (NEW) PARTNER

MUST USE CHECKED-SIGNATURES!

Due Date Thu at 9:00pm (Week 10)

Purpose Add input & memory to calculator

Exercises

In this assignment, you will continue working on your project to create a small "calculator," which you began in 8a. In this version, you will add support for user input and "memory" operations (storing, recalling, and clearing).

We strongly recommend keeping the board code close at hand!

To do so, you will use continuation-passing style (CPS), which you learned about in Lecture 23.

Adding Input

Last time, your eval function accepted a placeholder input. This time, eval should not accept any input up front; instead, it should suspend the computation and prompt the user for input before continuing. This means that eval will not always return a number; it will instead return a Result, which can be either a number (i.e., the final answer, as before) or a suspended computation.

(define-struct input [resume])
; AInput is a
(define AInput (signature [InputOf (Number -> Result)]))
; representing a suspended calculator computation awaiting user input
 
; a Result is a
(define Result (signature (mixed Number AInput)))
; where a Number is a final answer and a AInput is awaiting user input

Exercise 1 Design a function (: resume (AInput Number -> Result)) that continues the computation with the given input.

Writing eval directly, in the style of the 8a,

You can try this out as a thought experiment. What would you return in the e-in case?

will not support suspending the computation for input. Instead, you will use CPS.

; A Cont is a
(define Cont (signature (Number -> Result)))
; where the Number is the answer of the previous computation

Exercise 2 Unlike the previous assignment, the order in which you evaluate the program matters. In this assignment, you will evaluate expressions from left to right. In a comment, provide an example program using input where the answer is different if one evaluates left-to-right vs. right-to-left, and say what these answers are.

Exercise 3 Write a helper function (: eval/aux (Exp -> (Cont -> Result))). You should evaluate expressions left-to-right. Take some time to digest this signature; make sure you understand it before diving into the code! Refer to the lecture code if you are stuck.

Exercise 4 Revise eval so that it has the signature (: eval (Exp -> Result)), and revise run so that it has the signature (: run (S-Exp -> Result)) (you needn’t include simplify and compact). You should use run and resume to write tests.

Parsing New Expressions

Now you will add support for memory operations. Extend your Exp grammar to include the follow constructs.

; an (EM+Of Exp)
; represents a program that computes its argument and adds it to the value in memory
(define-struct e-m+ [arg])
; an EMr represents a program that recalls a value from memory
(define-struct e-mr [])
; an EMc represents a program that clears the value in memory (sets it to zero)
(define-struct e-mc [])
 
; an Exp is a
(define Exp (signature (mixed Number
                              (EOpOf Op Exp Exp)
                              (EM+Of Exp)
                              EMr
                              EMc
                              EIn)))
; representing a calculator program that can prompt for input and manipulate state

The s-exp syntax for these operations is (m+ e), (mr), (mc). An example in context:

'(+ (m+ 5) (+ (mc) (mr)))

Exercise 5 Revise your parse function to handle these new expressions. As before, it should fail gracefully (i.e., with an appropriate error message) if the input is invalid. You should also use this opportunity to fix any bugs in parse from the previous assignment.

Evaluating Memory Operations

Finally, you will add support for evaluating memory operations. As before, you should evaluate expressions left-to-right. Initially, the memory cell has value 0.

Exercise 6 The signatures for eval and run will not change, but the signatures for eval/aux and Cont will change in a significant way. Revise these signatures so that they support threading the current memory cell through the computation. Then revise the existing cases in eval/aux to be consistent with its new signature. Finally, revise eval to provide the initial value of the memory cell, which is 0.

Exercise 7 Revise eval/aux to include support for m+. It adds its argument to the current value of the memory cell, but returns 0 as the answer. For example,

(check-expect (run '(+ (m+ 5) (+ (m+ 2) (mr)))) 7)

Exercise 8 Revise eval/aux to include support for mr. It does not change the current value of the memory cell and returns the memory’s value as the answer.

Exercise 9 Revise eval/aux to include support for mc. It clears the current value of the memory cell and returns 0 as the answer. For example, (check-expect (run ’(+ (m+ 5) (+ (mc) (mr)))) 0)

Exercise 10 Write lots of tests! You should use all of the helper functions at your disposal, and also use quasiquoting to build larger examples out of smaller ones.