;;; This file has three parts: ;;; ;;; 1. a set of hints for writing lexical-address, ;;; 2. a (very spartan) structure of the code that you can fill in, ;;; 3. a set of examples that try to explain the structure. ;;; ;;; HINTS FOR writing the procedure lexical-address: ;;; ;;; 1. You must use the helpers in lambda-if-exp.scm to pick apart ;;; the input s, and then you must use the helpers in ;;; lexical-addr-exp-mod.scm to put them back together into ;;; s. ;;; ;;; 2. Follow the (input) grammar for an outline of your code for each ;;; procedure!! ;;; ;;; 3. Because the globally bound (free) variables may have an ;;; arbitrary position number, our test cases do not automatically ;;; check the result when there is more than one free variable in the ;;; expression. Hence, it will be up to *you* to make sure that the ;;; free variables have unique position numbers. Check the output of ;;; these tests by hand to be sure. ;;; ;;; 4. Test your procedures from the bottom up; i.e., test the ;;; procedures that are called by other procedures first. Use the ;;; expected results of helpers when testing procedures that call the ;;; helpers. ;;; ;;; 5. The easiest approach to writing the lexical-address procedure ;;; is to write at least two helping procedures. (Because of tail ;;; recursion you may need more!) In our design, shown schematically ;;; below, there are two helping procedures, which are described below ;;; the structure, with examples following it. ;;; Structure [omitted] ;;; Notes on lexical-address-helper: ;;; ;;; The procedure lexical-address-helper takes a parsed lambda-if-exp, ;;; exp, and a list of lists of symbols, var-table. In var-table, ;;; each of the sublists corresponds to a the variables declared in a ;;; region (i.e., globally or by a lambda). Look at the examples ;;; (below) for how lambda is handled. The last sublist in var-table ;;; always contains the free variables found in the expression. The ;;; next-to-last sublist, if any, always contains the list of ;;; variables declared in the outermost lambda surrounding the ;;; expression, and so on until one reaches the first sublist, which ;;; contains the list of variables declared in the closest surrounding ;;; lambda surrounding the expression. ;;; ;;; To obtain the starting value to pass to the initial call to ;;; lexical-address-helper, you will likely want to use free-vars for ;;; the lambda-if-exp grammar as a helper. This allows the position ;;; in the last sublist of var-table to be used as the unique position ;;; number for the lexical address of each free variable. ;;; Some examples: ;;; ;;; (lexical-address-helper (parse-expression 'x) ;;; '((p q r x y) (w z x) (car ls)) ) ;;; ==> (x : 0 3) ;;; (lexical-address-helper (parse-expression 'x) ;;; '((a b) (p q r) (x y) (car ls)) ) ;;; ==> (x : 2 0) ;;; (lexical-address-helper (parse-expression '(quote x)) ;;; '((a b) (p q r) (x y) (car ls)) ) ;;; ==> (quote x) ;;; (lexical-address-helper (parse-expression '(car ls)) ;;; '((car ls)) ) ;;; ==> ((car : 0 0) (ls : 0 1)) ;;; (lexical-address-helper (parse-expression '(car ls)) ;;; '((ls car)) ) ;;; ==> ((car : 0 1) (ls : 0 0)) ;;; ;;; The next sequence of examples traces what should happen with recursive ;;; calls on lambda expressions. Notice the way the list of variable lists ;;; (the second argument) changes with each recursive call below. ;;; ;;; ; Example 1: ;;; (lexical-address-helper (parse-expression ;;; '(lambda (q r p) ;;; (lambda (x y) (if (p u) (h x) (t y))))) ;;; '((h t u)) ) ; second argument with free vars ;;; ; Note: the list of free variables is ;;; ; a member of the list of variable lists ;;; ==> (lambda (q r p) ;;; (lambda (x y) ;;; (if ((p : 1 2) (u : 2 2)) ;;; ((h : 2 0) (x : 0 0)) ;;; ((t : 2 1) (y : 0 1))))) ;;; ;;; ; Example 2: ;;; (lexical-address-helper (parse-expression ;;; '(lambda (x y) (if (p u) (h x) (t y)))) ;;; '((q r p) (h t u)) ) ; second argument ;;; ==> (lambda (x y) ;;; (if ((p : 1 2) (u : 2 2)) ;;; ((h : 2 0) (x : 0 0)) ;;; ((t : 2 1) (y : 0 1)))) ;;; ;;; ; Example 3: ;;; (lexical-address-helper (parse-expression '(if (p u) (h x) (t y))) ;;; '((x y) (q r p) (h t u)) ) ; second argument ;;; ==> (if ((p : 1 2) (u : 2 2)) ;;; ((h : 2 0) (x : 0 0)) ;;; ((t : 2 1) (y : 0 1))) ;;; ;;; Notes on lexical-address-var-exp: ;;; ;;; The procedure lexical-address-var-exp takes a symbol, sym, and a ;;; var-table. You can assume that the symbol occurs in some sublist ;;; of the var-table. You want to form an address expression ;;; containing the sublist index and the index within that of the ;;; first occurence of sym; this is sym's lexical coordinates. ;;; ;;; Some examples: ;;; ;;; (lexical-address-var-exp 'p '((x y) (q r p) (h t u)) ) ==> (p : 1 2) ;;; (lexical-address-var-exp 'y '((x y) (q r p) (h t u)) ) ==> (y : 0 1) ;;; (lexical-address-var-exp 'u '((x y) (q r p) (h t u)) ) ==> (u : 2 2) ;;; (lexical-address-var-exp 't '((x y) (q r p) (h t u)) ) ==> (t : 2 1)