inference.scm 2.8 KB

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