(module type-environments mzscheme
  (provide (all-defined))
  (require (planet "" ("cobbe" "environment.plt" 3 0))
           "" ""
           (lib ""))
 ;; the initial type name environment - just the base types
  (define-syntax (define-tname-env stx)
    (syntax-case stx ()
      [(_ var [nm ty] ...)
           (define-syntax nm (lambda (stx) (raise-syntax-error 'type-check "type name used out of context" stx))) ...
           (define var
             (list (list #'nm ty) ...)))]))  
  ;; the initial set of available type names
  (define-tname-env initial-type-names
    [atom A]
    [Atom A]
    [Void -Void]
    [number N]
    [Number N]
    [boolean B]
    [symbol Sym]
    [Boolean B]
    [Symbol Sym]
    [str -String]
    [String -String]
    [Any Univ]
    [top Univ]
    [Port -Port]
    [num-exp -NE]
    [Option (-poly (a) (Un (make-value #f) a))]
    [Sexp -Sexp]
    [List (-lst Univ)]
    [Listof -Listof]
    [list-of -Listof]
  ;; the initial type variable environment - empty
  ;; this is used in the parsing of types
  (define initial-tvar-env

  ;; a parameter for the current type variables
  (define current-tvars (make-parameter initial-tvar-env))  
  ;; some utility functions for environments

  ;; extend that works on single arguments
  (define (extend env k v) (extend-env (list k) (list v) env))
  ;; takes two lists of sets to be added, which are either added one at a time, if the
  ;; elements are not lists, or all at once, if the elements are lists
  (define (extend/values kss vss env)
    (foldr (lambda (ks vs env) 
             (cond [(and (list? ks) (list? vs))                                      
                    (extend-env ks vs env)]
                   [(or (list? ks) (list? vs))
                    (tc-error "not both lists in extend/values")]
                   [else (extend-env (list ks) (list vs) env)]))
           env kss vss))
  ;; extend-env with the environment first.  pretty pointless, really
  (define (extend-multiple env ids types)
    (extend-env ids types env))