infer-early.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. ; Copyright (c) 1993-2008 by Richard Kelsey. See file COPYING.
  2. ; Type checking nodes.
  3. ; Entry point
  4. ; Because NODE is not the car of a pair, this depends on lambdas not being
  5. ; coerceable and literal nodes being coerced in place (instead of having a
  6. ; call inserted).
  7. (define (infer-definition-type node name)
  8. (set! *currently-checking* name)
  9. (let ((res (cond ((literal-node? node)
  10. (infer-literal-type node name))
  11. ((lambda-node? node)
  12. (infer-type node 0))
  13. ((name-node? node)
  14. (get-global-type (binding-place (node-ref node 'binding))))
  15. (else
  16. (bug "definition value is not a value node ~S" node)))))
  17. (set! *currently-checking* #f)
  18. res))
  19. (define (infer-literal-type node name)
  20. (let ((value (node-form node)))
  21. (cond ((vector? value)
  22. (let ((uvar (make-uvar name -1)))
  23. (do ((i 0 (+ i 1)))
  24. ((>= i (vector-length value)))
  25. (unify! uvar (type-check-thing (vector-ref value i)) value))
  26. (make-pointer-type (maybe-follow-uvar uvar))))
  27. (else
  28. (infer-type node 0)))))
  29. (define (type-check-thing thing)
  30. (if (variable? thing)
  31. (get-package-variable-type thing)
  32. (literal-value-type thing)))
  33. (define literal-operator (get-operator 'literal))
  34. (define (make-literal-node value)
  35. (make-node literal-operator value))
  36. ; Get the type of the variable - if it is a type-variable, then create a new
  37. ; one and relate the two; if it is a polymorphic pattern, instantiate it.
  38. (define (get-package-variable-type var)
  39. (let ((rep (variable-type var)))
  40. (cond ((eq? rep type/undetermined)
  41. (let ((type (make-uvar (variable-name var) -1)))
  42. (set-variable-type! var type)
  43. (set-uvar-source! type var)
  44. type))
  45. ((type-scheme? rep)
  46. (instantiate-type-scheme rep -1))
  47. (else
  48. rep))))
  49. ; Exported
  50. (define (get-variable-type var)
  51. (let ((rep (variable-type var)))
  52. (cond ((eq? rep type/undetermined)
  53. (bug "lexically bound variable ~S has no type" var))
  54. ((type-scheme? rep)
  55. (instantiate-type-scheme rep -1))
  56. (else
  57. rep))))
  58. ;----------------------------------------------------------------
  59. (define (infer-type node depth)
  60. (infer-any-type node depth #f))
  61. (define (infer-any-type node depth return?)
  62. (let ((type ((operator-table-ref inference-rules (node-operator-id node))
  63. node
  64. depth
  65. return?)))
  66. (set-node-type! node type)
  67. (maybe-follow-uvar type)))
  68. (define inference-rules
  69. (make-operator-table
  70. (lambda (node depth return?)
  71. (error "no type inference for node ~S" node))))
  72. (define (define-inference-rule name proc)
  73. (operator-define! inference-rules name #f proc))
  74. (define-inference-rule 'literal
  75. (lambda (node depth return?)
  76. (infer-literal (node-form node) node)))
  77. (define-inference-rule 'quote
  78. (lambda (node depth return?)
  79. (infer-literal (cadr (node-form node)) node)))
  80. (define (infer-literal value node)
  81. (literal-value-type value))
  82. (define (literal-value-type value)
  83. (or (maybe-literal-value-type value)
  84. (error "don't know type of literal ~S" value)))
  85. (define (maybe-literal-value-type value)
  86. (cond ((boolean? value)
  87. type/boolean)
  88. ((char? value)
  89. type/char)
  90. ((and (integer? value)
  91. (exact? value))
  92. type/integer)
  93. ((real? value)
  94. type/float)
  95. ((string? value)
  96. type/string)
  97. (((structure-ref eval-node unspecific?) value)
  98. type/unit) ; was type/null
  99. ((input-port? value)
  100. type/input-port)
  101. ((output-port? value)
  102. type/output-port)
  103. ((external-value? value)
  104. (external-value-type value))
  105. ((external-constant? value)
  106. type/integer)
  107. (else
  108. #f)))
  109. (define-inference-rule 'unspecific
  110. (lambda (node depth return?)
  111. type/unit))
  112. (define-inference-rule 'lambda
  113. (lambda (node depth return?)
  114. (let* ((uid (unique-id))
  115. (exp (node-form node))
  116. (var-types (map (lambda (name-node)
  117. (initialize-name-node-type name-node uid depth))
  118. (cadr exp)))
  119. (result (infer-any-type (caddr exp) depth #t)))
  120. ; stash the return type
  121. (set-lambda-node-return-type! node result)
  122. (make-arrow-type var-types result))))
  123. ; Create a new type variable for VAR.
  124. (define (initialize-name-node-type node uid depth)
  125. (let ((uvar (make-uvar (node-form node) depth uid)))
  126. (set-node-type! node uvar)
  127. (set-uvar-source! uvar node)
  128. uvar))
  129. ; Get the type of the variable - if it is a type-variable, then create a new
  130. ; one and relate the two; if it is a polymorphic pattern, instantiate it.
  131. ; How to pass the source?
  132. (define-inference-rule 'name
  133. (lambda (node depth return?)
  134. (let ((type (if (node-ref node 'binding)
  135. (get-global-type (binding-place (node-ref node 'binding)))
  136. (node-type node))))
  137. (if (not type)
  138. (bug "name node ~S has no type" node))
  139. (if (type-scheme? type)
  140. (instantiate-type-scheme type depth)
  141. type))))
  142. (define-inference-rule 'primitive
  143. (lambda (node depth return?)
  144. (let ((type (get-global-type (cdr (node-form node)))))
  145. (if (type-scheme? type)
  146. (instantiate-type-scheme type depth)
  147. type))))
  148. ; If no type is present, create a type variable.
  149. (define (get-global-type value)
  150. (if (location? value)
  151. (literal-value-type (contents value))
  152. (let ((has (maybe-follow-uvar (variable-type value))))
  153. (cond ((not (eq? has type/undetermined))
  154. has)
  155. (else
  156. (let ((type (make-uvar (variable-name value) -1)))
  157. (set-variable-type! value type)
  158. (set-uvar-source! type value)
  159. type))))))
  160. (define-inference-rule 'set!
  161. (lambda (node depth return?)
  162. (let* ((exp (node-form node))
  163. (type (infer-type (caddr exp) depth))
  164. (binding (node-ref (cadr exp) 'binding)))
  165. (if (not binding)
  166. (error "SET! on a local variable ~S" (schemify node)))
  167. (unify! type (variable-type (binding-place binding)) node)
  168. type/null)))
  169. (define-inference-rule 'call
  170. (lambda (node depth return?)
  171. (rule-for-calls (node-form node) node depth return?)))
  172. (define-inference-rule 'goto
  173. (lambda (node depth return?)
  174. (rule-for-calls (cdr (node-form node)) node depth return?)))
  175. (define (rule-for-calls proc+args node depth return?)
  176. (let ((proc (car proc+args))
  177. (args (cdr proc+args)))
  178. (cond ((lambda-node? proc)
  179. (rule-for-let node depth proc args return?))
  180. ((primitive-node? proc)
  181. (rule-for-primitives node depth (node-form proc) args return?))
  182. (else
  183. (rule-for-unknown-calls node depth proc+args return?)))))
  184. (define name-node? (node-predicate 'name))
  185. (define lambda-node? (node-predicate 'lambda))
  186. (define literal-node? (node-predicate 'literal))
  187. (define primitive-node? (node-predicate 'primitive))
  188. (define (rule-for-let node depth proc args return?)
  189. (let ((depth (+ depth 1))
  190. (uid (unique-id))
  191. (proc (node-form proc)))
  192. (do ((names (cadr proc) (cdr names))
  193. (vals args (cdr vals)))
  194. ((null? names))
  195. (let ((type (schemify-type (infer-type (car vals) depth) depth)))
  196. (if (type-scheme? type)
  197. (set-node-type! (car names) type)
  198. (unify! (initialize-name-node-type (car names) uid depth)
  199. type
  200. node))))
  201. (infer-any-type (caddr proc) depth return?)))
  202. (define (rule-for-primitives node depth primitive args return?)
  203. ((primitive-inference-rule primitive)
  204. args node depth return?))
  205. (define (rule-for-unknown-calls node depth proc+args return?)
  206. (let ((proc-type (infer-type (car proc+args) depth))
  207. (arg-types (infer-types (cdr proc+args) depth))
  208. (return-type (if return?
  209. (make-tuple-uvar 'result depth)
  210. (make-uvar 'result depth))))
  211. (unify! proc-type
  212. (make-arrow-type arg-types return-type)
  213. node)
  214. ; (if (= 244 (uvar-id return-type))
  215. ; (breakpoint "rule-for-unknown-calls"))
  216. (maybe-follow-uvar return-type)))
  217. (define (infer-types nodes depth)
  218. (map (lambda (node)
  219. (infer-type node depth))
  220. nodes))
  221. (define-inference-rule 'begin
  222. (lambda (node depth return?)
  223. (let loop ((exps (cdr (node-form node))) (type type/unit))
  224. (if (null? exps)
  225. type
  226. (loop (cdr exps)
  227. (infer-any-type (car exps)
  228. depth
  229. (or (not (null? (cdr exps)))
  230. return?)))))))
  231. (define-inference-rule 'if
  232. (lambda (node depth return?)
  233. (let ((args (cdr (node-form node))))
  234. (let ((test-type (infer-type (car args) depth))
  235. (true-type (infer-any-type (cadr args) depth return?))
  236. (false-type (infer-any-type (caddr args) depth return?)))
  237. (unify! test-type type/boolean node)
  238. (unify! true-type false-type node)
  239. true-type))))
  240. ; Unions haven't been completely implemented yet.
  241. ;
  242. ;(define-inference-rule 'type-case
  243. ; (lambda (node depth return?)
  244. ; (let ((args (cdr (node-form node))))
  245. ; (let ((type-id (cadr (node-form (cadr args))))
  246. ; (uvar (make-uvar 'v depth)))
  247. ; (let ((union-type (make-pointer-type (get-union-type type-id)))
  248. ; (cont-types (get-union-deconstruction-types type-id uvar)))
  249. ; (check-arg-type args 0 union-type depth node)
  250. ; (check-arg-types args 2 cont-types depth node)
  251. ; uvar)))))
  252. (define-inference-rule 'letrec
  253. (lambda (node depth return?)
  254. (let ((form (node-form node))
  255. (depth (+ depth 1))
  256. (uid (unique-id)))
  257. (let ((names (map car (cadr form)))
  258. (vals (map cadr (cadr form))))
  259. (for-each (lambda (name)
  260. (initialize-name-node-type name uid depth))
  261. names)
  262. (do ((names names (cdr names))
  263. (vals vals (cdr vals)))
  264. ((null? names))
  265. (if (not (lambda-node? (car vals)))
  266. (error "LETREC value is not a LAMBDA: ~S" (schemify node)))
  267. (unify! (infer-type (car vals) depth)
  268. (node-type (car names))
  269. node))
  270. (for-each (lambda (name)
  271. (let ((type (schemify-type (node-type name) depth)))
  272. (if (type-scheme? type)
  273. (set-node-type! name type))))
  274. names)
  275. (infer-any-type (caddr form) depth return?)))))
  276. ;--------------------------------------------------
  277. (define (node-type node)
  278. (maybe-follow-uvar (node-ref node 'type)))
  279. (define (set-node-type! node type)
  280. (node-set! node 'type type))
  281. (define (lambda-node-return-type node)
  282. (node-ref node 'return-type))
  283. (define (set-lambda-node-return-type! node type)
  284. (node-set! node 'return-type type))
  285. ;--------------------------------------------------
  286. ; Utility procedures used by the inferencers of the various primops.
  287. ; Check that the INDEX'th argument of CALL has type TYPE.
  288. (define (check-arg-type args index type depth exp)
  289. (if (null? args)
  290. (begin
  291. (format #t "Wrong number of arguments in ~S~% " (schemify exp))
  292. (if *currently-checking*
  293. (format #t "~% while reconstructing the type of '~S'" *currently-checking*))
  294. (error "type problem")))
  295. (unify! (infer-type (list-ref args index) depth)
  296. type
  297. exp))