C311 Assignment 2 (Static Properties)

;;
;; C311 Assignment 2
;; Static Properties
;; Due F 09/20/96 @ 5:00pm
;;


;; bound-vars
;; bound-vars gets an expression in the lambda calculus syntax, and
;; returns the set of variables that are bound in the expression.
;; it uses a helper procedure, b-vars that takes an expression and
;; a list of variables found to be bound earlier in the process (bsf
;; stands for "bounds-so-far".

(define bound-vars
  (letrec
    ([b-vars
       (lambda (exp bsf)
	 (if (variable? exp)
	     bsf			; base case? return the bsf set.
	     (record-case exp
	       (lambda (formals body)	; (car formals) is a new boud var
		 (if (memq (car formals) bsf) ; already there?
		     (b-vars body bsf)	; don't include it and check the body
		     (b-vars body (cons (car formals) bsf))))
	       				; include it and check the body
	       (else			; check rand and then rator
		 (b-vars (rator exp) (b-vars (rand exp) bsf))))))])
    (lambda (exp)
      (b-vars exp '()))))



;; bound?
;; bound? gets a variable and an expression in the lambda calculus
;; syntax, and returns #t if the variable is bound in that expression.

(define bound?
  (lambda (var exp)
    (if (variable? exp)			; variable alone? it is not bound
	#f
	(record-case exp
	  (lambda (formals body)	
	    (or (eq? (car formals) var)	; bound if the var is the formal
		(bound? var body)))	; or if it appears bound in the body
	  (else
	    (or
	      (bound? var (rator exp))	; bound if appears bound in rator/rand
	      (bound? var (rand exp))))))))



;; lexical-address
;; lexical-address takes any expression and returns the expression wih
;; every variable reference v replaced by a list (v : d p) where d is
;; the lexical depth and p is its declaration position, using zero-based
;; index for both p and d.
;; lex-addres is the procedure that does the work. It takes the expression
;; and an environment of the form ( (var00 var01 ... var0n) (var10 var11 ...
;; var1m) ... (vark0 vark1 ... varkl) ), where (var00 var01 ... var0n) is
;; the formals list of the expression nearest enclosing lambda. For instance,
;; when your whole expression is:
;;		(lambda (a b c)
;;		  (lambda (d e)
;;		    (lambda ()
;;		      (+ a b c d e))))
;; the environment when evaluating (+ a b c d e) will be:
;;		(() (d e) (a b c))
;; getaddress is another helper procedure that takes a variable, an
;; environment and a depth (initially 0) and returns the variable reference
;; with the format (v : d p), or (v : free) if v is not in the environment.
;; For instance, (getaddress 'a '(() (d e) (a b c)) 0) ==> '(a : 2 0)

(define lexical-address
  (letrec ([lex-address
	     (lambda (exp env)
	       (if (variable? exp)
		   (getaddress exp env 0)
		   (record-case exp
		     (lambda (formals body)
		       `(lambda ,formals
			  ,(lex-address body (cons formals env))))
		     (if (test then else)
			 `(if
			    ,(lex-address test env)
			    ,(lex-address then env)
			    ,(lex-address else env)))
		     (else (map (lambda (x) (lex-address x env)) exp)))))]
	   [getaddress
	     (lambda (var env depth)
	       (if (null? env)
		   (list var ': 'free)
		   (let ([offset (list-index var (car env))])
		     (if (=? offset -1)
			 (getaddress var (cdr env) (add1 depth))
			 (list var ': depth offset)))))])
    (lambda (exp)
      (lex-address exp '()))))

;; helper procedures.

(define variable? symbol?)
(define rator car)
(define rand cadr)

(define list-index
  (lambda (a ls)
    (letrec ([list-index-hlp
               (lambda (ls n)
                 (cond
                   [(null? ls) -1]
                   [(eq? (car ls) a) n]
                   [else (list-index-hlp
                           (cdr ls)
                           (add1 n))]))])
      (list-index-hlp ls 0))))



Last modified on Sat Sep 21 17:15:16 1996