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

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

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

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

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

> (or->if '(or))        ; or is false with no arguments
#f

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

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

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

Problem 3

Answer these questions about local variables as a syntactic abstraction.

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 a = x in (f a a)))
'(let a = (x : 0 0) in ((f : 1 1) (a : 0 0) (a : 0 0)))

> (lexical-address '(let a = g in
                         (let b = y in
                           (f a b))))
'(let a = (g : 0 0) in
   (let b = (y : 1 1) in
     ((f : 2 2) (a : 1 0) (b : 0 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 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) )))