123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
- ;;;
- ;;; Port Author: Andrew Whatson
- ;;;
- ;;; Original Authors: Richard Kelsey, Mike Sperber
- ;;;
- ;;; scheme48-1.9.2/ps-compiler/prescheme/inference.scm
- ;;;
- ;;; Type Inference
- ;;;
- ;;; The entry points to the inferencer are:
- ;;;
- ;;; (unify! type1 type2 context)
- ;;; Unify TYPE1 and TYPE2. CONTEXT is used to provide user feedback when type
- ;;; errors are detected.
- ;;;
- ;;; (make-uvar prefix depth . maybe-id)
- ;;; Makes a new type variable. PREFIX is a symbol, DEPTH is the current type
- ;;; depth (used for polymorphism), and MAYBE-ID is an optional unique
- ;;; integer.
- ;;;
- ;;; (schemify-type type depth)
- ;;; Make TYPE polymorphic in any variables bound at DEPTH.
- ;;;
- ;;; (instantiate-type-scheme scheme depth)
- ;;; Return an instantiation of SCHEME at DEPTH.
- ;;;
- ;;; (reset-inference!)
- ;;; Clear various global variables (to be replaced with fluids at some point)
- (define-module (ps-compiler prescheme inference)
- #:use-module (prescheme scheme48)
- #:use-module (prescheme bcomp node)
- #:use-module (prescheme bcomp schemify)
- #:use-module (ps-compiler prescheme type)
- #:use-module (ps-compiler prescheme type-var)
- #:use-module (ps-compiler util syntax)
- #:use-module (ps-compiler util util)
- #:export (unify!
- *currently-checking*))
- (define (unify! type1 type2 context)
- (cond ((really-unify! type1 type2)
- => (lambda (error-thunk)
- (unify-lost error-thunk type1 type2 context)))))
- (define *currently-checking* #f)
- (define *current-top-exp* #f)
- (define (unify-lost error-thunk type1 type2 context)
- (cond ((eq? context 'simplifying)
- (bug "unification error while instantiating an integrable procedure"))
- ((eq? context 'make-monomorphic)
- #f)
- (else
- (user-type-error-message error-thunk type1 type2 context))))
- (define (user-type-error-message error-thunk type1 type2 context)
- (format #t "Type error in ~S~% " (schemify context))
- (error-thunk)
- (if *currently-checking*
- (begin
- (format #t "~% while reconstructing the type of~% ")
- (*currently-checking* (current-output-port))))
- (error "type problem"))
- (define (really-unify! p1 p2)
- (let ((p1 (maybe-follow-uvar p1)) ;; get the current value of P1
- (p2 (maybe-follow-uvar p2))) ;; get the current value of P2
- (cond ((or (eq? p1 p2)
- (eq? p1 type/null)
- (eq? p2 type/null))
- #f)
- ((uvar? p1)
- (bind-uvar! p1 p2))
- ((uvar? p2)
- (bind-uvar! p2 p1))
- ((and (eq? p1 type/unit)
- (eq? p2 type/unit))
- #f)
- ((other-type? p1)
- (if (and (other-type? p2)
- (eq? (other-type-kind p1) (other-type-kind p2))
- (= (length (other-type-subtypes p1))
- (length (other-type-subtypes p2))))
- (unify-lists! (other-type-subtypes p1)
- (other-type-subtypes p2))
- (mismatch-failure p1 p2)))
- (else
- (mismatch-failure p1 p2)))))
- (define (mismatch-failure t1 t2)
- (lambda ()
- (format #t "type mismatch~% ")
- (display-type t1 (current-output-port))
- (format #t "~% ")
- (display-type t2 (current-output-port))))
- (define (unify-lists! l1 l2)
- (let loop ((l1 l1) (l2 l2))
- (if (null? l1)
- #f
- (or (really-unify! (car l1) (car l2))
- (loop (cdr l1) (cdr l2))))))
- (define (type-conflict message . stuff)
- (apply breakpoint message stuff))
- ;; For debugging
- (define (uvar-name uvar)
- (concatenate-symbol (uvar-prefix uvar) "." (uvar-id uvar)))
|