type.scm 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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/type.scm
  8. (define-module (ps-compiler prescheme type)
  9. #:use-module (srfi srfi-9)
  10. #:use-module (prescheme scheme48)
  11. #:use-module (prescheme record-discloser)
  12. #:use-module (ps-compiler prescheme record)
  13. #:use-module (ps-compiler prescheme type-scheme)
  14. #:use-module (ps-compiler prescheme type-var)
  15. #:use-module (ps-compiler util util)
  16. #:export (;;type/int7u
  17. ;;type/int8
  18. ;;type/int8u
  19. type/integer
  20. type/unsigned-integer
  21. type/float
  22. type/char
  23. type/address
  24. type/null
  25. type/unit
  26. type/boolean
  27. type/undetermined
  28. type/input-port
  29. type/output-port
  30. type/unknown
  31. type/string
  32. other-type?
  33. other-type-kind
  34. other-type-subtypes
  35. make-other-type
  36. base-type?
  37. base-type-name
  38. base-type-uid
  39. make-atomic-type
  40. make-arrow-type
  41. arrow-type?
  42. arrow-type-result
  43. arrow-type-args
  44. make-pointer-type
  45. pointer-type?
  46. pointer-type-to
  47. make-tuple-type
  48. tuple-type?
  49. tuple-type-types
  50. lookup-type
  51. type-eq?
  52. ;;type>
  53. ;;type>=
  54. ;;lattice-type?
  55. expand-type-spec
  56. finalize-type
  57. display-type
  58. make-base-type-table))
  59. (define-record-type :base-type
  60. (really-make-base-type name uid)
  61. base-type?
  62. (name base-type-name)
  63. (uid base-type-uid)) ;; an integer
  64. (define-record-discloser :base-type
  65. (lambda (base-type)
  66. (list (base-type-name base-type)
  67. (base-type-uid base-type))))
  68. (define *next-base-type-uid* 0)
  69. (define (next-base-type-uid)
  70. (let ((x *next-base-type-uid*))
  71. (set! *next-base-type-uid* (+ x 1))
  72. x))
  73. (define base-type-table (make-table))
  74. (define (make-base-type name)
  75. (let ((type (really-make-base-type name (next-base-type-uid))))
  76. (table-set! base-type-table name type)
  77. type))
  78. (define (lookup-type id)
  79. (cond ((table-ref base-type-table id)
  80. => identity)
  81. (else #f)))
  82. (define type/integer (make-base-type 'integer))
  83. (define type/unsigned-integer (make-base-type 'unsigned-integer))
  84. (define type/float (make-base-type 'float))
  85. (define type/null (make-base-type 'null)) ;; no value
  86. (define type/unit (make-base-type 'unit)) ;; single value
  87. (define type/boolean (make-base-type 'boolean))
  88. (define type/undetermined (make-base-type '?))
  89. (define type/input-port (make-base-type 'input-port))
  90. (define type/output-port (make-base-type 'output-port))
  91. (define type/address (make-base-type 'address))
  92. (define type/char (make-base-type 'char))
  93. (define (make-atomic-type name)
  94. (really-make-base-type name (next-base-type-uid)))
  95. (define type/unknown type/undetermined) ;; an alias
  96. (define (type-name type)
  97. (if (base-type? type)
  98. (base-type-name type)
  99. (error "type has no name ~S" type)))
  100. (define (make-base-type-table)
  101. (let ((elts (make-vector *next-base-type-uid* #f)))
  102. (values (lambda (type)
  103. (vector-ref elts (base-type-uid type)))
  104. (lambda (type value)
  105. (vector-set! elts (base-type-uid type) value)))))
  106. ;;--------------------------------------------------
  107. ;; This won't terminate on recursive types.
  108. (define (type-eq? type1 type2)
  109. (let ((type1 (maybe-follow-uvar type1))
  110. (type2 (maybe-follow-uvar type2)))
  111. (or (eq? type1 type2)
  112. (and (other-type? type1)
  113. (other-type? type2)
  114. (eq? (other-type-kind type1)
  115. (other-type-kind type2))
  116. (let loop ((l1 (other-type-subtypes type1))
  117. (l2 (other-type-subtypes type2)))
  118. (cond ((null? l1) (null? l2))
  119. ((null? l2) #f)
  120. ((type-eq? (car l1) (car l2))
  121. (loop (cdr l1) (cdr l2)))
  122. (else #f)))))))
  123. ;;--------------------------------------------------
  124. ;; Arrow and pointer types (and perhaps others later)
  125. ;; All done together to simplify the type walking
  126. (define-record-type :other-type
  127. (really-make-other-type kind subtypes finalized?)
  128. other-type?
  129. (kind other-type-kind)
  130. (subtypes other-type-subtypes set-other-type-subtypes!) ;; set when finalized
  131. (finalized? other-type-finalized? set-other-type-finalized?!))
  132. (define (make-other-type kind subtypes)
  133. (really-make-other-type kind subtypes #f))
  134. (define-record-discloser :other-type
  135. (lambda (type)
  136. (case (other-type-kind type)
  137. ((arrow)
  138. (list 'arrow-type
  139. (arrow-type-args type)
  140. (arrow-type-result type)))
  141. (else
  142. (cons (other-type-kind type)
  143. (other-type-subtypes type))))))
  144. (define (make-other-type-predicate kind)
  145. (lambda (x)
  146. (and (other-type? x)
  147. (eq? kind (other-type-kind x)))))
  148. ;; Arrow
  149. (define (make-arrow-type args result)
  150. (make-other-type 'arrow (cons result args)))
  151. (define arrow-type? (make-other-type-predicate 'arrow))
  152. (define (arrow-type-args type)
  153. (cdr (other-type-subtypes type)))
  154. (define (arrow-type-result type)
  155. (car (other-type-subtypes type)))
  156. ;; Pointer
  157. (define (make-pointer-type type)
  158. (make-other-type 'pointer (list type)))
  159. (define pointer-type? (make-other-type-predicate 'pointer))
  160. (define (pointer-type-to pointer-type)
  161. (car (other-type-subtypes pointer-type)))
  162. (define type/string (make-pointer-type type/char))
  163. ;; Tuple (used for arguments and returning multiple values)
  164. (define (make-tuple-type types)
  165. (if (and (not (null? types))
  166. (null? (cdr types)))
  167. (car types)
  168. (make-other-type 'tuple types)))
  169. (define tuple-type? (make-other-type-predicate 'tuple))
  170. (define (tuple-type-types type)
  171. (other-type-subtypes type))
  172. ;;--------------------------------------------------
  173. (define (finalize-type type)
  174. (let ((type (maybe-follow-uvar type)))
  175. (cond ((and (other-type? type)
  176. (not (other-type-finalized? type)))
  177. (let ((subs (other-type-subtypes type)))
  178. (set-other-type-finalized?! type #t)
  179. (set-other-type-subtypes! type (map finalize-type subs))))
  180. ((and (uvar? type)
  181. (uvar-tuple-okay? type)) ;; unused return value
  182. (bind-uvar! type type/unit)))
  183. type))
  184. ;;--------------------------------------------------
  185. (define (expand-type-spec spec)
  186. (cond ((pair? spec)
  187. (case (car spec)
  188. ((=>)
  189. (make-arrow-type (map expand-type-spec (cadr spec))
  190. (make-tuple-type (map expand-type-spec
  191. (cddr spec)))))
  192. ((^)
  193. (make-pointer-type (expand-type-spec (cadr spec))))
  194. ((tuple)
  195. (make-tuple-type (map expand-type-spec (cdr spec))))
  196. (else
  197. (error "unknown type syntax ~S" spec))))
  198. ((not (symbol? spec))
  199. (error "unknown type syntax ~S" spec))
  200. ((lookup-type spec)
  201. => identity)
  202. ((lookup-record-type spec)
  203. => make-pointer-type)
  204. (else
  205. (error "unknown type name ~S" spec))))
  206. ;;--------------------------------------------------
  207. (define (display-type type port)
  208. (define (do-list list)
  209. (write-char #\( port)
  210. (cond ((not (null? list))
  211. (do-type (car list))
  212. (for-each (lambda (type)
  213. (write-char #\space port)
  214. (do-type type))
  215. (cdr list))))
  216. (write-char #\) port))
  217. (define (do-type type)
  218. (let ((type (maybe-follow-uvar type)))
  219. (cond ((base-type? type)
  220. (display (base-type-name type) port))
  221. ((record-type? type)
  222. (display (record-type-name type) port))
  223. ((arrow-type? type)
  224. (write-char #\( port)
  225. (do-list (arrow-type-args type))
  226. (display " -> " port)
  227. (do-type (arrow-type-result type))
  228. (write-char #\) port))
  229. ((pointer-type? type)
  230. (write-char #\* port)
  231. (do-type (pointer-type-to type)))
  232. ((uvar? type)
  233. (write-char #\T port)
  234. (display (uvar-id type) port))
  235. ((type-scheme? type)
  236. (display "(for-all " port)
  237. (do-list (type-scheme-free-uvars type))
  238. (display " " port)
  239. (do-type (type-scheme-type type))
  240. (display ")" port))
  241. ((tuple-type? type)
  242. (display "(tuple " port)
  243. (do-list (tuple-type-types type))
  244. (display ")" port))
  245. (else
  246. (bug "don't know how to display type ~S" type)))))
  247. (do-type type))