racket/collects/tests/eopl/chapter8/full-system/checker.rkt
David Van Horn 7491e172ea EOPL test suite re-written in Racket-based #lang eopl and rackunit
The eopl language is now racket-based rather than mzscheme-based.  This
test-suite, which was originally distributed on the book's web-site has
been re-written in the new language.  Changes include dropping all
drscheme-init.scm and top.scm files.  Remaining files were renamed to
use the .rkt extension and edited to use the #lang syntax (instead of
modulue).  Require and provide forms were changed to reflect racket's
syntax instead of mzscheme's (eg, only-in vs. only).  Several
occurrences of one-armed ifs were changed to use when and unless.  All
tests have been run successfully.
2012-02-24 14:46:18 -05:00

125 lines
4.4 KiB
Racket
Executable File

#lang eopl
(require "lang.rkt")
(require "static-data-structures.rkt")
(require "expand-type.rkt")
(provide type-of)
;; check-equal-type! : Type * Type * Exp -> Unspecified
;; Page: 242
(define check-equal-type!
(lambda (ty1 ty2 exp)
(unless (equal? ty1 ty2)
(report-unequal-types ty1 ty2 exp))))
;; report-unequal-types : Type * Type * Exp -> Unspecified
;; Page: 243
(define report-unequal-types
(lambda (ty1 ty2 exp)
(eopl:error 'check-equal-type!
"Types didn't match: ~s != ~a in~%~a"
(type-to-external-form ty1)
(type-to-external-form ty2)
exp)))
;;;;;;;;;;;;;;;; The Type Checker ;;;;;;;;;;;;;;;;
;; moved to check-modules.scm
;; type-of-program : Program -> Type
;; Page: 244
;; (define type-of-program
;; (lambda (pgm)
;; (cases program pgm
;; (a-program (exp1)
;; (type-of exp1 (init-tenv))))))
;; type-of : Exp * Tenv -> Type
;; Page 244--246. See also page 285.
(define type-of
(lambda (exp tenv)
(cases expression exp
(const-exp (num) (int-type))
(diff-exp (exp1 exp2)
(let ((type1 (type-of exp1 tenv))
(type2 (type-of exp2 tenv)))
(check-equal-type! type1 (int-type) exp1)
(check-equal-type! type2 (int-type) exp2)
(int-type)))
(zero?-exp (exp1)
(let ((type1 (type-of exp1 tenv)))
(check-equal-type! type1 (int-type) exp1)
(bool-type)))
(if-exp (exp1 exp2 exp3)
(let ((ty1 (type-of exp1 tenv))
(ty2 (type-of exp2 tenv))
(ty3 (type-of exp3 tenv)))
(check-equal-type! ty1 (bool-type) exp1)
(check-equal-type! ty2 ty3 exp)
ty2))
(var-exp (var) (apply-tenv tenv var))
;; lookup-qualified-var-in-tenv defined on page 285.
(qualified-var-exp (m-name var-name)
(lookup-qualified-var-in-tenv m-name var-name tenv))
(let-exp (var exp1 body)
(let ((rhs-type (type-of exp1 tenv)))
(type-of body (extend-tenv var rhs-type tenv))))
(proc-exp (bvar bvar-type body)
(let ((expanded-bvar-type
(expand-type bvar-type tenv)))
(let ((result-type
(type-of body
(extend-tenv
bvar
expanded-bvar-type
tenv))))
(proc-type expanded-bvar-type result-type))))
(call-exp (rator rand)
(let ((rator-type (type-of rator tenv))
(rand-type (type-of rand tenv)))
(cases type rator-type
(proc-type (arg-type result-type)
(begin
(check-equal-type! arg-type rand-type rand)
result-type))
(else
(eopl:error 'type-of
"Rator not a proc type:~%~s~%had rator type ~s"
rator (type-to-external-form rator-type))))))
(letrec-exp (proc-result-type proc-name
bvar bvar-type
proc-body
letrec-body)
(let ((tenv-for-letrec-body
(extend-tenv
proc-name
(expand-type
(proc-type bvar-type proc-result-type)
tenv)
tenv)))
(let ((proc-result-type
(expand-type proc-result-type tenv))
(proc-body-type
(type-of proc-body
(extend-tenv
bvar
(expand-type bvar-type tenv)
tenv-for-letrec-body))))
(check-equal-type!
proc-body-type proc-result-type proc-body)
(type-of letrec-body tenv-for-letrec-body))))
)))
;; type environments are now in static-data-structures.rkt .