Homework 8
Creating a Syntactic Abstraction

Due: Monday, April 6, at 11:59 PM

Introduction

For this assignment, you will extend our little language with a new syntactic abstraction and write a function to do static analysis of programs in the language. It should help you understand more deeply the idea of syntactic sugar and prepare you to implement your own.

Template Source Files

Download the zipped directory hw08.zip. which contains two files that you will modify:

  • You will extend syntax-procs.rkt to support and and or expressions.
  • You will modify the preprocessor in homework08.rkt in two ways:
    • You will extend preprocess to handle the new syntactic abstractions and and or.
    • You will add two new static analysis functions that processes programs in the core little language.

The zip file also contains:

The first two define functions that are used in the other files. You will not modify them. The third, homework08-tests.rkt, contains my tests for the existing functionality. You may add tests to that file for the code you write, if you want, but you are not required to do so.

Organizing Code

Be sure to update the header blocks in syntax-procs.rkt and homework08.rkt with your personal information.

Put any helper functions you write for a problem after the main function of your solution.

If you create any generic helper functions to use in your code, you may add them to utilities.rkt, if you'd like.
(If you do, email me the file. The submission system will not request it.)

You do not have to write Rackunit tests for the functions you write. However, I strongly encourage you to evaluate your code using the examples I give in the assignment and to think of other cases that test your functions.

For this assignment, you may use Racket let expressions and any other Racket functions we have learned in class. You may not use an internal define — use a let expression instead!

The Little Language

You will begin with the little language we saw in Session 19, extended with a one-variable let expression like the one we saw in Session 17. For this assignment, you will add two new syntactic abstractions: and and or.

          --------------------------- CORE FEATURES
<exp> ::= <varref>
        | (lambda (<var>*) <exp>)
        | (<exp> <exp>*)
        | (if <exp> <exp> <exp>)
          --------------------------- ABSTRACTIONS
        | (let (<var> <exp>) <exp>)
        | (and <exp> <exp>)           -- new
        | (or <exp> <exp>)            -- new

The core language consists of variable references, lambda expressions, applications, and if expressions.

The full language contains the core features plus local variables (let expressions) and boolean operators (and and or expressions). let, and, and or expressions are syntactic abstractions.

Note that any function that processes an expression in the core language should consider only four cases: variable references, lambda expressions, applications, and if expressions.

Problems

  1. Write syntax procedures for the new and and or expressions.

    For each, write a constructor, a type predicate, and accessors for the parts of the expression. Name the accessors:

    • and->arg1
    • and->arg2
    • or->arg1
    • or->arg1

    and and or are new keywords in the language. Add them to the list of keywords in the keyword? function, found in the variable references section of the file.

    Remember two things...

    • Add your type predicates to the general exp? type predicate, because and and or expressions are now legal expressions, too.
    • Add your syntax procedures to the provide clause at the top of the file, so that other files can use them.
  2. Modify preprocess to translate and and or expressions into equivalent if expressions, following the definitions you saw in your reading.

    Use the symbols 'TRUE and 'FALSE in place of boolean literals for true and false.

    Test your translations by passing programs that contain and and or expressions to the preprocessor to ensure they produce the expected output. You can also pass preprocessed and and or expressions to one of the static analysis functions in the homework08.rkt file.

    Here are a few sample expressions to test:

    (or a b)
    (lambda (x) (and x y))
    (f (or on paused))
    (if (and j k) a b)
    (let (a (f x)) (if (and x y) a b))
    ((if (and x y) f g) height weight)
    
  3. Write a structurally recursive function named (is-declared? v exp) that takes two arguments, a symbol and an expression in the core language.

    is-declared? returns true if v is declared as a variable anywhere in exp, and false otherwise.

    For example:

    > (is-declared? 'y 'y)
    #f
    > (is-declared? 'x '(lambda (x) x))
    #t
    > (is-declared? 'x '(lambda (y) x))
    #f
    > (is-declared? 'y '(f (lambda (y) x)))
    #t
    > (is-declared? 'x '( (lambda (y) y)      ; x is not declared here
                          (lambda (x) x) ))   ; but x is declared here
    #t
    
    Remember two things...
    • Only a lambda expression can declare a variable in the core language.
    • A lambda expression can occur inside of other expressions, including a lambda expression.

    You must use the syntax procedures for the little language to implement your function.

    Note: You wrote a version of this function for Quiz 2. Feel free to use your exam code, and any comments I made on it, as a starting point here.

  4. Write a structurally recursive function named (shadowed-vars exp) that takes one argument, an expression in the core language.

    (shadowed-vars exp) returns a list of all the variable declarations in exp that are shadowed by another variable of the same name. A variable is shadowed if it is redeclared in the body of a lambda expression.

    For example:

    > (shadowed-vars '(lambda (x) (f x)))
    '()
    
    > (shadowed-vars '(lambda (f)
                        (lambda (x)
                          (f (lambda (f)
                               (f x))))))
    '(f)
    

    You will want to use your is-declared? function from Problem 2 as a helper!

    Recall that, if two expressions return flat lists and you need to combine them into a single flat list, use the append function, rather than cons.

    more hints

Deliverables

By the due time and date, use the course submission system to submit the following files electronically:

If you add functions to utilities.rkt or to homework08-tests.rkt, please email those files to me as well.

Be sure that your submission follows the submission requirements. Be sure to use the specified names for your files. This enables the auto-grader to find and run your code.