+(define (last xs)
+ (if (null? (cdr xs))
+ (car xs)
+ (last (cdr xs))))
+
+
+(define (normalize prog) ; (+ a b) -> ((+ a) b)
+ (case (ast-type prog)
+ ('lambda
+ ; (lambda (x y) (+ x y)) -> (lambda (x) (lambda (y) (+ x y)))
+ (if (> (length (lambda-args prog)) 1)
+ (list 'lambda (list (car (lambda-args prog)))
+ (normalize (list 'lambda (cdr (lambda-args prog)) (caddr prog))))
+ (list 'lambda (lambda-args prog) (normalize (caddr prog)))))
+ ('app
+ (if (null? (cddr prog))
+ `(,(normalize (car prog)) ,(normalize (cadr prog))) ; (f a)
+ `(,(list (normalize (car prog)) (normalize (cadr prog)))
+ ,(normalize (caddr prog))))) ; (f a b)
+ ;; (list (list (normalize (car prog))
+ ;; (normalize (cadr prog))) (normalize (caddr prog))))) ; (f a b)
+ ('let
+ (append (list 'let
+ (map (lambda (x) `(,(car x) ,(normalize (cadr x))))
+ (let-bindings prog)))
+ (map normalize (let-body prog))))
+ ('if `(if ,(normalize (cadr prog))
+ ,(normalize (caddr prog))
+ ,(normalize (cadddr prog))))
+ (else prog)))
+
+(define (builtin-type x)
+ (case x
+ ('+ '(abs int (abs int int)))
+ ('- '(abs int (abs int int)))
+ ('* '(abs int (abs int int)))
+ ('! '(abs bool bool))
+ ('= '(abs int (abs int bool)))
+ ('bool->int '(abs bool int))
+ (else #f)))
+
+; we typecheck the lambda calculus only (only single arg lambdas)
+(define (typecheck prog)
+ (define (check env x)
+ ;; (display "check: ")
+ ;; (display x)
+ ;; (display "\n\t")
+ ;; (display env)
+ ;; (newline)