File: type-var.scm

package info (click to toggle)
scheme48 1.8%2Bdfsg-1%2Bdeb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 14,984 kB
file content (154 lines) | stat: -rw-r--r-- 4,512 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
; Copyright (c) 1993-2008 by Richard Kelsey.  See file COPYING.


; Type variables - what a mess

(define-record-type uvar :uvar
  (really-make-uvar prefix depth id tuple-okay?
	     place source binding temp)		; all initialized to #F
  uvar?
  (prefix  uvar-prefix)			  ; a name for debugging
  (depth   uvar-depth set-uvar-depth!)	  ; lexical depth of the uvar
  (id      uvar-id)			  ; a number
  ; true if this can be unified with a tuple, set when merged
  (tuple-okay? uvar-tuple-okay? set-uvar-tuple-okay?!)
  (place   uvar-place   set-uvar-place!)  ; used in producing type schemes
  (source  uvar-source  set-uvar-source!)
  ; to let the user know where this came from
  (binding uvar-binding set-uvar-binding!); known value of this uvar
  (temp    uvar-temp    set-uvar-temp!))  ; useful field

(define-record-discloser :uvar
  (lambda (uvar)
    (list 'uvar
	  (uvar-prefix uvar)
	  (uvar-depth uvar)
	  (uvar-id uvar)
	  (uvar-binding uvar))))

(define (make-uvar prefix depth . maybe-id)
  (really-make-uvar prefix
		    depth
		    (if (null? maybe-id)
			(unique-id)
			(car maybe-id))
		    #f			; tuple-okay?
		    #f #f #f #f))	; place source binding temp

(define (make-tuple-uvar prefix depth . maybe-id)
  (really-make-uvar prefix
		    depth
		    (if (null? maybe-id)
			(unique-id)
			(car maybe-id))
		    #t			; tuple-okay?
		    #f #f #f #f))	; place source binding temp

; Could this safely short-circuit the chains?

(define (maybe-follow-uvar type)
  (cond ((and (uvar? type)
	      (uvar-binding type))
	 => maybe-follow-uvar)
	(else type)))

; Substitute VALUE for UVAR, if this will not introduce a circularity.
; or cause other problems.  Returns an error-printing thunk if there is
; a problem.

(define (bind-uvar! uvar value)
  (cond ((uvar? value)
	 (bind-uvar-to-uvar! uvar value)
	 #f)
	(else
	 (bind-uvar-to-type! uvar value))))

(define (bind-uvar-to-uvar! uvar0 uvar1)
  (minimize-type-depth! uvar1 (uvar-depth uvar0))
  (set-uvar-binding! uvar0 uvar1)
  (if (and (uvar-tuple-okay? uvar1)
	   (not (uvar-tuple-okay? uvar0)))
      (set-uvar-tuple-okay?! uvar1 #f)))

(define (bind-uvar-to-type! uvar type)
  (let ((errors '()))
    (if (uvar-in-type? uvar type)
	(set! errors (cons circularity-error errors)))
    (if (and (tuple-type? type)
	     (not (uvar-tuple-okay? uvar)))
	(set! errors (cons (tuple-error type) errors)))
    (cond ((null? errors)  ; whew!
	   (minimize-type-depth! type (uvar-depth uvar))
	   (set-uvar-binding! uvar type)
	   #f)
	  (else
	   (lambda ()
	     (format #t "unifying ")
	     (display-type uvar (current-output-port))
	     (format #t " == ")
	     (display-type type (current-output-port))
	     (format #t "~% would cause the following problem~A:"
		     (if (null? (cdr errors)) "" "s"))
	     (for-each (lambda (x) (x)) errors))))))
		       
(define (circularity-error)
  (format #t "~% creation of a circular type"))

(define (tuple-error type)
  (lambda ()
    (if (null? (tuple-type-types type))
	(format #t "~% returning no values where one is expected")
	(format #t "~% returning ~D values where one is expected"
		(length (tuple-type-types type))))))

; Check that UVAR does not occur in EXP.

(define (uvar-in-type? uvar exp)
  (let label ((exp exp))
    (cond ((or (base-type? exp)
	       (record-type? exp))
	   #f)
	  ((uvar? exp)
	   (if (uvar-binding exp)
	       (label (uvar-binding exp))
	       (eq? exp uvar)))
	  ((other-type? exp)
	   (every? label (other-type-subtypes exp)))
	  (else
	   (identity (bug "funny type ~S" exp))))))
  
; Make the depths of any uvars in TYPE be no greater than DEPTH.

(define (minimize-type-depth! type depth)
  (let label ((type type))
    (cond ((other-type? type)
	   (for-each label (other-type-subtypes type)))
	  ((uvar? type)
	   (cond ((uvar-binding type)
		  => label)
		 ((< depth (uvar-depth type))
		  (set-uvar-depth! type depth)))))))

; Set the depth of all uvars in TYPE to be -1 so that it will not be made
; polymorphic at any level.

(define (make-nonpolymorphic! type)
  (cond ((uvar? type)
	 (set-uvar-depth! type -1))
	((other-type? type)
	 (for-each make-nonpolymorphic! (other-type-subtypes type)))
	;((type-scheme? type)
	; (make-nonpolymorphic! (type-scheme-type type)))
	))

;------------------------------------------------------------
; Micro utilities

(define *unique-id-counter* 0)

(define (unique-id)
  (set! *unique-id-counter* (+ *unique-id-counter* 1))
  *unique-id-counter*)

(define (reset-type-vars!)
  (set! *unique-id-counter* 0))