infer-early.scm 13 KB

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