Quiz 3: Syntactic Abstraction

Instructions

Problem 1

Give brief answers to each of these questions about syntactic abstraction. One sentence each should be sufficient for the first and second bullets — two sentences each max.

Problem 2

Answer these questions about local variables as a syntactic abstraction.

The designers of your favorite programming language have decided to eliminate local variables from the next version of language. "No problem", you think. "Local variables are a syntactic abstraction."

Problem 3

Write a recursive function (and->if and-exp), where and-exp is described by this grammar:

<and-exp> ::= (and . <arglist>)

<arglist> ::= '()
            | (<symbol> . <arglist>)

and->if returns an equivalent if expression. For example:

> (and->if '(and))        ; and is true with no arguments
#t

> (and->if '(and x y))
'(if x (if y #t #f) #f)

> (and->if '(and a b c d e))
'(if a (if b (if c (if d (if e #t #f) #f) #f) #f) #f)

Hint: Make and->if an interface procedure that strips the symbol 'and from the front of its argument and calls a helper function on the list of symbols.

Problem 4

Answer each of these questions about lexical addresses.

Problem 5

On Homework 7, we added a let expression to our little language.

Add a case to the definition of lexical-address-helper so that it can handle let expressions.

See the language details on the next page.

((let? exp)        ; a new case for let expressions
    ; FILL-IN-THE-BLANK
)

The Little Language for Problem 5

Problem 5 uses the little language we worked with on our lexical addressing exercise in Sessions 19-20, extended with a let expression.

<exp> ::= <varref>
        | (lambda (<var>*) <exp>)
        | (<exp> . <exp>*)
        | (if <exp> <exp> <exp>)
        | (let (<var> <exp>) <exp>)     <--- new from Homework 7

Like a Racket let expression, this let expression creates a new block declaring an identifier. The region of the local variable is the body of the let expression. References to a local variable within the body of the let are at a depth of 0. For example:

> (lexical-address '(let (x n)
                      (f (g x))))
'(let (x (n : 0 0))
   ((f : 1 1) ((g : 1 2) (x : 0 0))))

> (lexical-address '(let (width n)
                      (let (height m)
                        (f height (* width width)))))
'(let (width (n : 0 0))
   (let (height (m : 1 1))
     ((f : 2 2) (height : 0 0) ((* : 2 3) (width : 1 0) (width : 1 0)))))

Use the syntax procedures for let expressions to write your code:

let?      make-let      let->var    let->val    let->body

The Existing Code for lexical-address-helper

(define lexical-address-helper
  (lambda (exp list-of-decls)
    (cond ((varref? exp)
             (lexical-address-for exp list-of-decls 0))
          ((if? exp)
             (make-if (lexical-address-helper (if->test exp) list-of-decls)
                      (lexical-address-helper (if->then exp) list-of-decls)
                      (lexical-address-helper (if->else exp) list-of-decls)))
          ((app? exp)
             (make-app (lexical-address-helper (app->proc exp) list-of-decls)
                       (map (lambda (e)
                              (lexical-address-helper e list-of-decls))
                            (app->args exp))))
          ((lambda? exp)
             (make-lambda (lambda->params exp)
                          (lexical-address-helper
                            (lambda->body exp)
                            (cons (lambda->params exp) list-of-decls))))
          (else (error 'lexical-address "unknown exp ~a" exp) ))))