inference.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Mike Sperber
  3. ; Type Inference
  4. ;
  5. ; The entry points to the inferencer are:
  6. ;
  7. ; (unify! type1 type2 context)
  8. ; Unify TYPE1 and TYPE2. CONTEXT is used to provide user feedback when type
  9. ; errors are detected.
  10. ;
  11. ; (make-uvar prefix depth . maybe-id)
  12. ; Makes a new type variable. PREFIX is a symbol, DEPTH is the current type
  13. ; depth (used for polymorphism), and MAYBE-ID is an optional unique
  14. ; integer.
  15. ;
  16. ; (schemify-type type depth)
  17. ; Make TYPE polymorphic in any variables bound at DEPTH.
  18. ;
  19. ; (instantiate-type-scheme scheme depth)
  20. ; Return an instantiation of SCHEME at DEPTH.
  21. ;
  22. ; (reset-inference!)
  23. ; Clear various global variables (to be replaced with fluids at some point)
  24. (define (unify! type1 type2 context)
  25. (cond ((really-unify! type1 type2)
  26. => (lambda (error-thunk)
  27. (unify-lost error-thunk type1 type2 context)))))
  28. (define *currently-checking* #f)
  29. (define *current-top-exp* #f)
  30. (define (unify-lost error-thunk type1 type2 context)
  31. (cond ((eq? context 'simplifying)
  32. (bug "unification error while instantiating an integrable procedure"))
  33. ((eq? context 'make-monomorphic)
  34. #f)
  35. (else
  36. (user-type-error-message error-thunk type1 type2 context))))
  37. (define (user-type-error-message error-thunk type1 type2 context)
  38. (format #t "Type error in ~S~% " (schemify context))
  39. (error-thunk)
  40. (if *currently-checking*
  41. (begin
  42. (format #t "~% while reconstructing the type of~% ")
  43. (*currently-checking* (current-output-port))))
  44. (error "type problem"))
  45. (define (really-unify! p1 p2)
  46. (let ((p1 (maybe-follow-uvar p1)) ; get the current value of P1
  47. (p2 (maybe-follow-uvar p2))) ; get the current value of P2
  48. (cond ((or (eq? p1 p2)
  49. (eq? p1 type/null)
  50. (eq? p2 type/null))
  51. #f)
  52. ((uvar? p1)
  53. (bind-uvar! p1 p2))
  54. ((uvar? p2)
  55. (bind-uvar! p2 p1))
  56. ((and (eq? p1 type/unit)
  57. (eq? p2 type/unit))
  58. #f)
  59. ((other-type? p1)
  60. (if (and (other-type? p2)
  61. (eq? (other-type-kind p1) (other-type-kind p2))
  62. (= (length (other-type-subtypes p1))
  63. (length (other-type-subtypes p2))))
  64. (unify-lists! (other-type-subtypes p1)
  65. (other-type-subtypes p2))
  66. (mismatch-failure p1 p2)))
  67. (else
  68. (mismatch-failure p1 p2)))))
  69. (define (mismatch-failure t1 t2)
  70. (lambda ()
  71. (format #t "type mismatch~% ")
  72. (display-type t1 (current-output-port))
  73. (format #t "~% ")
  74. (display-type t2 (current-output-port))))
  75. (define (unify-lists! l1 l2)
  76. (let loop ((l1 l1) (l2 l2))
  77. (if (null? l1)
  78. #f
  79. (or (really-unify! (car l1) (car l2))
  80. (loop (cdr l1) (cdr l2))))))
  81. (define (type-conflict message . stuff)
  82. (apply breakpoint message stuff))
  83. ; For debugging
  84. (define (uvar-name uvar)
  85. (concatenate-symbol (uvar-prefix uvar) "." (uvar-id uvar)))