home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacHaskell 2.2 / type / type-macros.scm < prev    next >
Encoding:
Text File  |  1994-09-27  |  5.0 KB  |  163 lines  |  [TEXT/CCL2]

  1.  
  2. ;;; This file also contains some random globals for the type checker:
  3.  
  4. (define-walker type ast-td-type-walker)
  5.  
  6. ;;; Some pre-defined types
  7. (define *bool-type* '())
  8. (define *char-type* '())
  9. (define *string-type* '())
  10. (define *int-type* '())
  11. (define *integer-type* '())
  12. (define *rational-type* '())
  13. (define *dynamic-type* '())
  14. (define *signature-type* '())
  15. (define *magic-type* '())
  16.  
  17. ;;; These two globals are used throughout the typechecker to avoid
  18. ;;; passing lots of stuff in each function call.
  19.  
  20. (define *placeholders* '())
  21. (define *non-generic-tyvars* '())
  22. (define *enclosing-decls* '())
  23.  
  24. ;;; Used by the defaulting mechanism
  25.  
  26. (define *default-decls* '())
  27.  
  28. ;;; Used in error handling & recovery
  29.  
  30. (define *type-error-handlers* '())
  31. (define *type-error-recovery* '())
  32.  
  33.  
  34. ;;; This associates a type checker function with an ast type.  The variable
  35. ;;; `object' is bound to the value being types.
  36.  
  37. (define-syntax (define-type-checker ast-type . cont)
  38.   `(define-walker-method type ,ast-type (object)
  39.      ,@cont))
  40.  
  41. ;;; This recursively type checks a structure slot in the current object.
  42. ;;; This updates the ast in the slot (since type checking rewrites the ast)
  43. ;;; and binds the computed type to a variable.  The slot must contain an
  44. ;;; expression.
  45.  
  46. (define-syntax (type-check struct slot var . cont)
  47.   `(mlet ((($$$ast$$$ ,var)
  48.        (dispatch-type-check (struct-slot ',struct ',slot object))))
  49.      (setf (struct-slot ',struct ',slot object) $$$ast$$$)
  50.      ,@cont))
  51.  
  52. ;;; This is used to scope decls.
  53.  
  54. (define-syntax (with-new-tyvars . cont)
  55.   `(dynamic-let ((*non-generic-tyvars* (dynamic *non-generic-tyvars*)))
  56.      ,@cont))
  57.  
  58.  
  59. ;;; Similar to type-check, the slot must contain a list of decls.
  60. ;;; This must be done before any reference to a variable defined in the
  61. ;;; decls is typechecked.
  62.         
  63. (define-syntax (type-check/decls struct slot . cont)
  64.   `(with-new-tyvars
  65.     (let (($$$decls$$$
  66.       (type-decls (struct-slot ',struct ',slot object))))
  67.      (setf (struct-slot ',struct ',slot object) $$$decls$$$)
  68.      ,@cont)))
  69.  
  70. ;;; The type checker returns an expression / type pair.  This
  71. ;;; abstracts the returned value.
  72.  
  73. (define-syntax (return-type object type)
  74.   `(values ,object ,type))
  75.  
  76. ;;; When an ast slot contains a list of expressions, there are two
  77. ;;; possibilities: the expressions all share the same type or each has
  78. ;;; an independant type.  In the first case, a single type (computed
  79. ;;; by unifying all types in the list) is bound to a variable.
  80.  
  81. (define-syntax (type-check/unify-list struct slot var error-handler . cont)
  82.   `(mlet ((($$$ast$$$ $$$types$$$)
  83.        (do-type-check/list (struct-slot ',struct ',slot object))))
  84.     (setf (struct-slot ',struct ',slot object) $$$ast$$$)
  85.     (with-type-error-handler ,error-handler ($$$types$$$)
  86.        (unify-list/single-type $$$types$$$)
  87.        (let ((,var (car $$$types$$$)))
  88.      ,@cont))))
  89.  
  90. ;;; When a list of expressions does not share a common type, the result is
  91. ;;; a list of types.
  92.  
  93. (define-syntax (type-check/list struct slot var . cont)
  94.   `(mlet ((($$$ast$$$ ,var)
  95.        (do-type-check/list (struct-slot ',struct ',slot object))))
  96.     (setf (struct-slot ',struct ',slot object) $$$ast$$$)
  97.     ,@cont))
  98.  
  99. ;;; This creates a fresh tyvar and binds it to a variable.
  100.  
  101. (define-syntax (fresh-type var . cont)
  102.   `(let ((,var (**ntyvar)))
  103.      ,@cont))
  104.  
  105. ;;; This drives the unification routine.  Two types are unified and the
  106. ;;; context is updated.  Currently no error handling is implemented to
  107. ;;; deal with unification errors.
  108.  
  109. (define-syntax (type-unify type1 type2 error-handler)
  110.   `(with-type-error-handler ,error-handler ()
  111.      (unify ,type1 ,type2)))
  112.  
  113. ;;; This generates a fresh set of monomorphic type variables.
  114.  
  115. (define-syntax (fresh-monomorphic-types n vars . cont)
  116.   `(with-new-tyvars
  117.      (let ((,vars '()))
  118.        (dotimes (i ,n)
  119.        (let ((tv (**ntyvar)))
  120.          (push tv ,vars)
  121.          (push tv (dynamic *non-generic-tyvars*))))
  122.        ,@cont)))
  123.  
  124. ;;; This creates a single monomorphic type variable.
  125.  
  126. (define-syntax (fresh-monomorphic-type var . cont)
  127.   `(let* ((,var (**ntyvar)))
  128.      (with-new-tyvars
  129.        (push ,var (dynamic *non-generic-tyvars*))
  130.        ,@cont)))
  131.  
  132. ;;; This is used to rewrite the current ast as a new ast and then
  133. ;;; recursively type check the new ast.  The original ast is saved for
  134. ;;; error message printouts.
  135.  
  136. (define-syntax (type-rewrite ast)
  137.   `(mlet (((res-ast type) (dispatch-type-check ,ast))
  138.       (res (**save-old-exp object res-ast)))
  139.       (return-type res type)))
  140.  
  141. ;;; These are the type error handlers
  142.  
  143. (define-syntax (recover-type-error error-handler . body)
  144.  (let ((temp (gensym))
  145.        (err-fn (gensym)))
  146.   `(let/cc ,temp
  147.     (let ((,err-fn ,error-handler))
  148.      (dynamic-let ((*type-error-recovery*
  149.             (cons (lambda ()
  150.                 (funcall ,err-fn ,temp))
  151.               (dynamic *type-error-recovery*))))
  152.         ,@body)))))
  153.  
  154. (define-syntax (with-type-error-handler handler extra-args . body)
  155.   (if (eq? handler '#f)
  156.       `(begin ,@body)
  157.       `(dynamic-let ((*type-error-handlers*
  158.               (cons (lambda ()
  159.                  (,(car handler) ,@extra-args ,@(cdr handler)))
  160.                 (dynamic *type-error-handlers*))))
  161.         ,@body)))
  162.  
  163.