scsh-0.6/ps-compiler/prescheme/type-scheme.scm

108 lines
2.8 KiB
Scheme

; Copyright (c) 1994 by Richard Kelsey. See file COPYING.
; Type schemes
(define-record-type type-scheme
(
type ; a type
free-uvars ; uvars that are free
)
())
(define make-type-scheme type-scheme-maker)
(define-record-discloser type/type-scheme
(lambda (type-scheme)
(list 'type-scheme
(map uvar-id (type-scheme-free-uvars type-scheme))
(type-scheme-type type-scheme))))
; If TYPE has any variables bound at DEPTH this returns a type scheme making
; those variables polymorphic; otherwise TYPE is returned.
; Would like to do limited finalizing of uvars, but can't.
; Consider (lambda (g x) (tuple (g 3) (g x) x))
; (a -> b) -> c -> [d, e, f] with
; a > int8, d > b, a > c, e > b, f > c
; No polymorphism, and no simplification without restricting someone
; But consider NOT a ->b, bool > a, b > bool
; It could just as well be bool -> bool.
; Simplification okay on variables that are not used inside other types?
(define *free-uvars* '())
(define (schemify-type type depth)
(set! *free-uvars* '())
(let* ((type (find-free-uvars type depth))
(free-uvars *free-uvars*))
(set! *free-uvars* '()) ; drop pointers
(for-each (lambda (uvar)
(set-uvar-place! uvar #f))
free-uvars)
(if (not (null? free-uvars))
(make-type-scheme type free-uvars)
type)))
(define (find-free-uvars type depth)
(let label ((type type))
(cond ((other-type? type)
(make-other-type (other-type-kind type)
(map label
(other-type-subtypes type))))
((not (uvar? type))
type)
((uvar-binding type)
=> label)
((and (not (uvar-place type))
(<= depth (uvar-depth type)))
(set-uvar-place! type type)
(set! *free-uvars* (cons type *free-uvars*))
type)
(else
type))))
; Instantiate SCHEME at DEPTH.
;
; New sequence:
; (instantiate-type-scheme scheme depth)
; ... elide bindings in new copy ...
; (clean-type-scheme scheme)
(define (instantiate-type-scheme scheme depth . maybe-thunk)
(instantiate-type-scheme! scheme depth)
(let ((type (copy-type (type-scheme-type scheme))))
(if (not (null? maybe-thunk))
((car maybe-thunk)))
(clean-type-scheme! scheme)
type))
(define (instantiate-type-scheme! scheme depth)
(let ((uid (unique-id)))
(for-each (lambda (uvar)
(set-uvar-place!
uvar
(make-uvar (uvar-prefix uvar) depth uid)))
(type-scheme-free-uvars scheme))))
(define (clean-type-scheme! scheme)
(for-each (lambda (uvar)
(set-uvar-place! uvar #f))
(type-scheme-free-uvars scheme)))
(define (copy-type type)
(cond ((other-type? type)
(make-other-type (other-type-kind type)
(map copy-type
(other-type-subtypes type))))
((not (uvar? type))
type)
((uvar-place type)
=> identity)
((uvar-binding type)
=> copy-type)
(else
type)))