racket/collects/tests/eopl/chapter8/full-system/check-modules.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

127 lines
5.5 KiB
Racket
Executable File

#lang eopl
(require "lang.rkt")
(require "static-data-structures.rkt")
(require "expand-type.rkt")
(require "checker.rkt")
(require "renaming.rkt")
(require "subtyping.rkt")
(require (only-in racket pretty-print))
(provide type-of-program)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; type-of-program : Program -> Type
;; Page: 286
(define type-of-program
(lambda (pgm)
(cases program pgm
(a-program (module-defs body)
(type-of body
(add-module-defns-to-tenv module-defs (empty-tenv)))))))
;; add-module-defns-to-tenv : Listof(ModuleDefn) * Tenv -> Tenv
;; Page: 286, 305
(define add-module-defns-to-tenv
(lambda (defns tenv)
(if (null? defns)
tenv
(cases module-definition (car defns)
(a-module-definition (m-name expected-iface m-body)
(let ((actual-iface (interface-of m-body tenv)))
(if (<:-iface actual-iface expected-iface tenv)
;; ok, continue in extended tenv
(let ((new-env (extend-tenv-with-module
m-name
(expand-iface m-name expected-iface tenv)
tenv)))
(add-module-defns-to-tenv (cdr defns) new-env))
;; no, raise error
(report-module-doesnt-satisfy-iface m-name
expected-iface actual-iface))))))))
;; interface-of : ModuleBody * Tenv -> Iface
;; Page: 322
(define interface-of
(lambda (m-body tenv)
(cases module-body m-body
(var-module-body (m-name)
(lookup-module-name-in-tenv tenv m-name))
(defns-module-body (defns)
(simple-iface
(defns-to-decls defns tenv)))
(app-module-body (rator-id rand-id)
(let ((rator-iface (lookup-module-name-in-tenv tenv rator-id))
(rand-iface (lookup-module-name-in-tenv tenv rand-id)))
(cases interface rator-iface
(simple-iface (decls)
(eopl:error 'interface-of
"attempt to apply non-parameterized module ~s"
rator-id))
(proc-iface (param-name param-iface result-iface)
(if (<:-iface
rand-iface
param-iface tenv)
(rename-in-iface
result-iface param-name rand-id)
(raise-bad-module-application-error! param-iface
rand-iface m-body)))
(else (eopl:error 'interface-of
"unknown module type ~s"
rator-iface))
)))
(proc-module-body (rand-name rand-iface m-body)
;; add the formal parameter to the tenv as if it had been a
;; top-level module.
(let ((body-iface
(interface-of m-body
(extend-tenv-with-module rand-name
(expand-iface rand-name rand-iface tenv)
tenv))))
(proc-iface rand-name rand-iface body-iface)))
)))
;; defns-to-decls : Listof(Defn) * Tenv -> Listof(Decl)
;; Page: 288, 305
;; Convert defns to a set of declarations for just the names defined
;; in defns. Do this in the context of tenv. The tenv is extended
;; at every step, so we get the correct let* scoping
(define defns-to-decls
(lambda (defns tenv)
(if (null? defns)
'()
(cases definition (car defns)
(val-defn (var-name exp)
(let ((ty (type-of exp tenv)))
(let ((new-env (extend-tenv var-name ty tenv)))
(cons
(val-decl var-name ty)
(defns-to-decls (cdr defns) new-env)))))
(type-defn (name ty)
(let ((new-env (extend-tenv-with-type
name
(expand-type ty tenv)
tenv)))
(cons
(transparent-type-decl name ty)
(defns-to-decls (cdr defns) new-env))))))))
(define raise-bad-module-application-error!
(lambda (expected-type rand-type body)
(pretty-print
(list 'bad-module-application body
'actual-rand-interface: rand-type
'expected-rand-interface: expected-type))
(eopl:error 'interface-of
"Bad module application ~s" body)))
(define report-module-doesnt-satisfy-iface
(lambda (m-name expected-type actual-type)
(pretty-print
(list 'error-in-defn-of-module: m-name
'expected-type: expected-type
'actual-type: actual-type))
(eopl:error 'type-of-module-defn)))