; AR ::= (make-var symbol) | (make-const integer) | (make-proc var AR) |
;        (make-app (AR AR)
(define-struct var (symbol))   
(define-struct const (number)) 
(define-struct proc (var body))
(define-struct app (rator rand))
; Note type contracts on structures is given in definition of AR above

; template for processing AR (LC abstract representation/syntax)

(define fAR
  (lambda (an-ar ...)  ; an-ar is an ar
    (cond
      ((var? an-ar) ... (var-symbol an-ar) ...)
      ((const? an-ar) ... (const-number an-ar) ...)
      ((proc? an-ar)  ... (fAR (proc-body an-ar)) ...)
      ((app? an-ar) ... (fAR (app-rator an-ar))
                        (fAR (app-rand an-ar)) ... ))))

; SDAR ::= (make-sdvar integer) | (make-const integer) | (make-sdproc SDAR) |
;          (make-app SDAR SDAR)

(define-struct sdvar (index))
(define-struct sdproc (body))
         
(define ar1 (make-app (make-proc (make-var 'x) (make-var 'x)) (make-const 1)))
(define sdar1 (make-app (make-sdproc (make-sdvar 1)) (make-const 1))) 
(define (sd an-ar binding-vars)
  ;; convert an-ar in conventional abstract syntax to static distance syntax where
  ;;   binding-vars is a list specifying the environment of conventional variable names
  (cond
    ((var? an-ar) (make-sdvar (sdlookup (var-symbol an-ar) binding-vars)))
    ((const? an-ar) an-ar)
    ((proc? an-ar) (make-sdproc (sd (proc-body an-ar) (cons (var-symbol (proc-var an-ar)) binding-vars))))
    ((app? an-ar) (make-app (sd (app-rator an-ar) binding-vars)
                        (sd (app-rand an-ar) binding-vars)))))


(define (sdlookup sym binding-vars)
  ;; returns index of matching var in binding-vars
  (cond
    ((null? binding-vars) (error "~a occurs free in program" sym))
    (else 
     (cond ((eq? sym (car binding-vars)) 1)
           (else (add1 (sdlookup sym (cdr binding-vars))))))))
    