polytype.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. ;;; POLYTYPE -- A polymorphic type inferencer for Scheme.
  2. (test-begin "polytype" 1)
  3. ;------------------------------------------------------------------------------
  4. ;
  5. ; A polymorphic type inferencer for Scheme
  6. ;
  7. ; Marc Feeley (05/16/88)
  8. ;
  9. ; Modified by Per Bothner (Febrary 2012) to fit into SRFI-64 test framework
  10. ;------------------------------------------------------------------------------
  11. ;------------------------------------------------------------------------------
  12. ;
  13. ; Error handling.
  14. (define (fail msg) (error "error:" msg))
  15. ;------------------------------------------------------------------------------
  16. ;
  17. ; An environment is an object that associates variables to values. They are
  18. ; represented by association lists.
  19. (define (env-empty) ; returns an empty environment
  20. '())
  21. (define (env-update var val env) ; returns a copy of 'env' but with 'var'
  22. (cons (cons var val) env)) ; associated to 'val'
  23. (define (env-join env1 env2) ; return a new environment containing the bindings
  24. (append env1 env2)) ; in env1 and env2 (env1 has precedence)
  25. (define (env-bound? var env) ; returns true if the variable is bound in 'env'
  26. (assq var env))
  27. (define (env-value var env) ; returns the value associated to 'var' in 'env'
  28. (cdr (assq var env)))
  29. ;------------------------------------------------------------------------------
  30. ;
  31. ; Variables are symbols starting with a "?" (e.g. ?a)
  32. (define variable-count #f)
  33. (define (new-variable)
  34. (set! variable-count (+ variable-count 1))
  35. (string->symbol (string-append "?" (number->string variable-count))))
  36. (define (variable? x)
  37. (and (symbol? x) (char=? (string-ref (symbol->string x) 0) #\?)))
  38. (define (variable<? x y)
  39. (string<? (symbol->string x) (symbol->string y)))
  40. ;------------------------------------------------------------------------------
  41. ;
  42. ; The unifier.
  43. (define (unify x y initial-env) ; return the values that must be substituted
  44. (define (uni x y env) ; for the variables so that x and y unify
  45. (let ((x* (deref x env))
  46. (y* (deref y env)))
  47. (cond ((eq? x* y*)
  48. env)
  49. ((and (variable? x*) (or (not (variable? y*)) (variable<? y* x*)))
  50. (env-update x* y* env))
  51. ((variable? y*)
  52. (env-update y* x* env))
  53. ((and (pair? x*) (pair? y*))
  54. (uni (cdr x*) (cdr y*) (uni (car x*) (car y*) env)))
  55. (else
  56. (fail "can not unify the two structures")))))
  57. (uni x y initial-env))
  58. (define (deref var env) ; get the value of a variable
  59. (if (variable? var)
  60. (if (env-bound? var env)
  61. (deref (env-value var env) env)
  62. var)
  63. var))
  64. (define (substitute x env) ; return x, where each variable is substituted for
  65. (cond ((variable? x) ; the value it is associated to in env
  66. (let ((y (deref x env)))
  67. (if (variable? y) y (substitute y env))))
  68. ((pair? x)
  69. (cons (substitute (car x) env) (substitute (cdr x) env)))
  70. (else
  71. x)))
  72. ;------------------------------------------------------------------------------
  73. (define (instance x prefix) ; generate an instance of x with new variables
  74. (define (new x env success) ; in place of the generic variables in prefix
  75. (cond ((and (variable? x) (generic? x prefix))
  76. (if (env-bound? x env)
  77. (success (env-value x env) env)
  78. (let ((var (new-variable)))
  79. (success var (env-update x var env)))))
  80. ((pair? x)
  81. (new (car x) env
  82. (lambda (a env)
  83. (new (cdr x) env
  84. (lambda (b env)
  85. (success (cons a b) env))))))
  86. (else
  87. (success x env))))
  88. (new x (env-empty) (lambda (a env) a)))
  89. (define (generic? var prefix) ; is the variable 'var' generic in the 'prefix'
  90. (cond ((null? prefix)
  91. #t)
  92. ((and (eq? (cadar prefix) var) (not (eq? (caar prefix) 'let)))
  93. #f)
  94. (else
  95. (generic? var (cdr prefix)))))
  96. ;------------------------------------------------------------------------------
  97. (define global-var-types
  98. '(
  99. (+ . (-> num num num))
  100. (- . (-> num num num))
  101. (* . (-> num num num))
  102. (/ . (-> num num num))
  103. (< . (-> num num bool))
  104. (<= . (-> num num bool))
  105. (= . (-> num num bool))
  106. (>= . (-> num num bool))
  107. (char>? . (-> char char bool))
  108. (char<? . (-> char char bool))
  109. (char<=? . (-> char char bool))
  110. (char=? . (-> char char bool))
  111. (char>=? . (-> char char bool))
  112. (char>? . (-> char char bool))
  113. (cons . (-> ?a (list ?a) (list ?a)))
  114. (car . (-> (list ?a) ?a))
  115. (cdr . (-> (list ?a) (list ?a)))
  116. (set-car! . (-> (list ?a) ?a ()))
  117. (set-cdr! . (-> (list ?a) (list ?a) ()))
  118. (null? . (-> (list ?a) bool))
  119. (length . (-> (list ?a) num))
  120. (append . (-> (list ?a) (list ?a) (list ?a)))
  121. (reverse . (-> (list ?a) (list ?a)))
  122. (map . (-> (-> ?a ?b) (list ?a) (list ?b)))
  123. (not . (-> bool bool))
  124. (call/cc . (-> (-> (-> ?a ?b) ?c) ?a))
  125. (apply . (-> (-> ?a ?b) (list ?a) ?b)) ; works for monadic procs only
  126. (write . (-> ?a ()))
  127. )
  128. )
  129. (define (constant-type x)
  130. (cond ((number? x) 'num)
  131. ((char? x) 'char)
  132. ((or (eq? x #t) (eq? x #f)) 'bool)
  133. ((null? x) '(list ?a))
  134. ((pair? x)
  135. (let ((element-type (constant-type (car x))))
  136. (for-each (lambda (y)
  137. (if (not (equal? (constant-type y) element-type))
  138. (fail "list is not homogenous")))
  139. (cdr x))
  140. (list 'list element-type)))
  141. (else (fail "unknown constant type"))))
  142. (define (quoted-constant-type x)
  143. (if (eq? x '())
  144. '(list ?a) ; patch because #f = ()
  145. (constant-type x)))
  146. (define (map-left-right f lst)
  147. (let loop ((lst lst))
  148. (if (pair? lst)
  149. (let ((x (f (car lst))))
  150. (cons x (loop (cdr lst))))
  151. '())))
  152. (define (map-left-right2 f lst1 lst2)
  153. (let loop ((lst1 lst1) (lst2 lst2))
  154. (if (pair? lst1)
  155. (let ((x (f (car lst1) (car lst2))))
  156. (cons x (loop (cdr lst1) (cdr lst2))))
  157. '())))
  158. (define (type f) ; return the type of expression 'f'
  159. (define e (env-empty))
  160. (define (j p f) ; algorithm 'j' from Robin Milner's paper
  161. (cond ((symbol? f)
  162. (if (env-bound? f p)
  163. (let ((x (env-value f p)))
  164. (let ((kind (car x))
  165. (type (cadr x)))
  166. (if (eq? kind 'let) (instance type p) type)))
  167. (instance (cdr (assq f global-var-types)) (env-empty))))
  168. ((not (pair? f))
  169. (instance (constant-type f) (env-empty)))
  170. ((eq? (car f) 'quote)
  171. (instance (quoted-constant-type (cadr f)) (env-empty)))
  172. ((eq? (car f) 'if)
  173. (let* ((pre (j p (cadr f)))
  174. (con (j p (caddr f)))
  175. (alt (j p (cadddr f))))
  176. (set! e (unify con alt (unify pre 'bool e)))
  177. con))
  178. ((eq? (car f) 'lambda)
  179. (let ((parms (map-left-right (lambda (x) (new-variable)) (cadr f))))
  180. (let ((body
  181. (j (env-join (map-left-right2
  182. (lambda (x y) (list x 'lambda y))
  183. (cadr f)
  184. parms)
  185. p)
  186. (caddr f))))
  187. (cons '-> (append parms (list body))))))
  188. ((eq? (car f) 'let)
  189. (j (env-join (map-left-right
  190. (lambda (x) (list (car x) 'let (j p (cadr x))))
  191. (cadr f))
  192. p)
  193. (caddr f)))
  194. ((eq? (car f) 'letrec)
  195. (let ((p* (env-join (map-left-right
  196. (lambda (x)
  197. (list (car x) 'letrec (new-variable)))
  198. (cadr f))
  199. p)))
  200. (for-each
  201. (lambda (x)
  202. (let ((val (j p* (cadr x))))
  203. (set! e (unify (cadr (env-value (car x) p*)) val e))))
  204. (cadr f))
  205. (j p* (caddr f))))
  206. ((and (pair? (car f)) (eq? (caar f) 'lambda))
  207. (j p (list 'let
  208. (map-left-right2 list (cadar f) (cdr f))
  209. (caddar f))))
  210. (else
  211. (let* ((result (new-variable))
  212. (oper (j p (car f)))
  213. (args (map-left-right (lambda (x) (j p x)) (cdr f))))
  214. (set! e (unify oper (cons '-> (append args (list result))) e))
  215. result))))
  216. (let ((t (j (env-empty) f)))
  217. (substitute t e)))
  218. ;------------------------------------------------------------------------------
  219. ;
  220. ; Some examples:
  221. (define example1
  222. '(cdr '(1 2 3)))
  223. (define example2
  224. '(lambda (x y) (if (car x) (car y) (length y))))
  225. (define example3
  226. '(letrec ((fact (lambda (x) (if (< x 2) 1 (* x (fact (- x 1)))))))
  227. fact))
  228. (define example4
  229. '(let ((ident (lambda (x) x))) (ident ident)))
  230. (define example5
  231. '(letrec ((length (lambda (l) (if (null? l) 0 (+ 1 (length (cdr l)))))))
  232. length))
  233. (define example6
  234. '(letrec ((map (lambda (f l)
  235. (if (null? l) '() (cons (f (car l)) (map f (cdr l)))))))
  236. map))
  237. (define example7
  238. '(lambda (x)
  239. (+ 4 (call/cc (lambda (exit)
  240. (if (null? x) (exit 0) (length x)))))))
  241. (define (run)
  242. (set! variable-count 0)
  243. (let* ((e1 (type example1))
  244. (e2 (type example2))
  245. (e3 (type example3))
  246. (e4 (type example4))
  247. (e5 (type example5))
  248. (e6 (type example6))
  249. (e7 (type example7)))
  250. (list e1 e2 e3 e4 e5 e6 e7)))
  251. (define expected
  252. '((list num)
  253. (-> (list bool) (list num) num)
  254. (-> num num)
  255. (-> ?20 ?20)
  256. (-> (list ?24) num)
  257. (-> (-> ?33 ?34) (list ?33) (list ?34))
  258. (-> (list ?51) num)))
  259. ;(define (main . args)
  260. ; (run-benchmark
  261. ; "polytype"
  262. ; polytype-iters
  263. ; (lambda () (run))
  264. ; (lambda (result) (equal? result expected))))
  265. (test-equal expected (run))
  266. (test-end)