flatten.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/prescheme/flatten.scm
  8. ;;;
  9. ;;; Definitions are (<variable> . <value>) pairs, where <value> can be any
  10. ;;; Scheme value. This code walks the values looking for sharing and for
  11. ;;; closures. Shared values are collected in a list and additional definitions
  12. ;;; are introduced for the bindings in the environments of closures and for
  13. ;;; close-compiled versions of any primitives in non-call position. References
  14. ;;; to closure-bound variables are replaced with references to the newly-created
  15. ;;; package variables.
  16. (define-module (ps-compiler prescheme flatten)
  17. #:use-module (srfi srfi-69)
  18. #:use-module (prescheme scheme48)
  19. #:use-module (prescheme s48-defrecord)
  20. #:use-module (prescheme bcomp node)
  21. #:use-module (prescheme bcomp binding)
  22. #:use-module (prescheme bcomp schemify)
  23. #:use-module (prescheme bcomp syntax)
  24. #:use-module (ps-compiler node variable)
  25. #:use-module (ps-compiler prescheme eval)
  26. #:use-module ((ps-compiler prescheme form) #:select (variable-set!? make-form))
  27. #:use-module (ps-compiler prescheme linking)
  28. #:use-module (ps-compiler prescheme primitive)
  29. #:use-module (ps-compiler prescheme substitute)
  30. #:use-module (ps-compiler prescheme type)
  31. #:use-module (ps-compiler util util)
  32. #:export (flatten-definitions
  33. generated-top-variable?
  34. make-primitive-node))
  35. (define (flatten-definitions definitions)
  36. (set! *shared* '())
  37. (set! *definitions* '())
  38. (set! *immutable-value-table* (make-value-table))
  39. (set! *closed-compiled-primitives* (make-symbol-table))
  40. (let loop ((defs definitions) (flat '()))
  41. (cond ((not (null? defs))
  42. (let ((var (caar defs))
  43. (value (cdar defs)))
  44. (if (and (variable-set!? var)
  45. (closure? value))
  46. (let ((new (generate-top-variable (variable-name var))))
  47. (loop `((,var . ,new)
  48. (,new . ,value)
  49. . ,defs)
  50. flat))
  51. (loop (cdr defs)
  52. (cons (cons var (flatten-value value))
  53. flat)))))
  54. ((null? *definitions*)
  55. (let ((forms (really-make-forms flat *shared*)))
  56. (set! *shared* #f) ;; safety
  57. (set! *closed-compiled-primitives* #f)
  58. (set! *immutable-value-table* #f)
  59. forms))
  60. (else
  61. (let ((defs *definitions*))
  62. (set! *definitions* '())
  63. (loop defs flat))))))
  64. ;; <Definitions> is a list of (<variable> . <value>) pairs.
  65. ;; <Shared> is a list of all shared objects, each of which must end up being
  66. ;; bound to a variable.
  67. (define (really-make-forms definitions shared)
  68. (for-each (lambda (defn)
  69. (let ((var (car defn))
  70. (shared (value-shared (cdr defn))))
  71. (if (and (not (variable-set!? var))
  72. shared
  73. (not (shared-variable shared)))
  74. (set-shared-variable! shared var))))
  75. definitions)
  76. (map definition->form
  77. (append definitions
  78. (shared-values->definitions shared))))
  79. (define (shared-values->definitions shared)
  80. (do ((shared shared (cdr shared))
  81. (defns '() (if (shared-variable (value-shared (car shared)))
  82. defns
  83. (let ((var (generate-top-variable #f)))
  84. (set-shared-variable! (value-shared (car shared)) var)
  85. (cons (cons var (car shared)) defns)))))
  86. ((null? shared)
  87. defns)))
  88. (define (definition->form definition)
  89. (let* ((var (car definition))
  90. (value (cdr definition))
  91. (shared (value-shared value))
  92. (value (if (or (not shared)
  93. (eq? var (shared-variable shared)))
  94. value
  95. (shared-variable shared)))
  96. (clean (clean-value! value)))
  97. (make-form
  98. var
  99. (if (or (node? clean)
  100. (variable? clean))
  101. clean
  102. (make-literal-node clean))
  103. (if (closure? value)
  104. (cdr (shared-saved (closure-temp value))) ;; free vars
  105. (stored-value-free-vars clean)))))
  106. (define (make-literal-node value)
  107. (make-node op/literal value))
  108. (define (make-name-node value)
  109. (make-node op/name value))
  110. (define *shared* '())
  111. (define (add-shared! value)
  112. (set! *shared* (cons value *shared*)))
  113. (define *definitions* '())
  114. (define (add-package-definition! value id)
  115. (let ((var (generate-top-variable id)))
  116. (set! *definitions*
  117. (cons (cons var value)
  118. *definitions*))
  119. var))
  120. (define (generate-top-variable maybe-id)
  121. (let ((var (make-global-variable (concatenate-symbol
  122. (if maybe-id
  123. (schemify maybe-id)
  124. 'top.)
  125. (next-top-id))
  126. type/undetermined)))
  127. (set-variable-flags! var
  128. (cons 'generated-top-variable
  129. (variable-flags var)))
  130. var))
  131. (define *next-top-id* 0)
  132. (define (next-top-id)
  133. (let ((id *next-top-id*))
  134. (set! *next-top-id* (+ 1 *next-top-id*))
  135. id))
  136. (define (generated-top-variable? var)
  137. (memq? 'generated-top-variable (variable-flags var)))
  138. (define (stored-value-free-vars value)
  139. (let ((vars '()))
  140. (let label ((value value))
  141. (cond ((variable? value)
  142. (cond ((not (variable-flag value))
  143. (set-variable-flag! value #t)
  144. (set! vars (cons value vars)))
  145. (else
  146. ;;(breakpoint "marked variable") ;; why did I care?
  147. (values))))
  148. ((vector? value)
  149. (do ((i 0 (+ i 1)))
  150. ((= i (vector-length value)))
  151. (label (vector-ref value i))))
  152. ((pair? value)
  153. (label (car value))
  154. (label (cdr value)))))
  155. (for-each (lambda (var)
  156. (set-variable-flag! var #f))
  157. vars)
  158. vars))
  159. ;;----------------------------------------------------------------
  160. ;; Finding shared data structures.
  161. (define-record-type shared
  162. ()
  163. (saved
  164. (shared? #f)
  165. (variable #f)))
  166. (define make-shared shared-maker)
  167. (define (value-shared value)
  168. (cond ((pair? value)
  169. (car value))
  170. ((vector? value)
  171. (if (= 0 (vector-length value))
  172. #f
  173. (vector-ref value 0)))
  174. ((closure? value)
  175. (closure-temp value))
  176. (else
  177. #f)))
  178. (define (clean-value! value)
  179. (cond ((pair? value)
  180. (cons (clean-sub-value! (shared-saved (car value)))
  181. (clean-sub-value! (cdr value))))
  182. ((vector? value)
  183. (if (= 0 (vector-length value))
  184. value
  185. (let ((new (make-vector (vector-length value))))
  186. (vector-set! new 0 (clean-sub-value!
  187. (shared-saved (vector-ref value 0))))
  188. (do ((i 1 (+ i 1)))
  189. ((= i (vector-length value)))
  190. (vector-set! new i (clean-sub-value! (vector-ref value i))))
  191. new)))
  192. ((closure? value)
  193. (car (shared-saved (closure-temp value)))) ;; flattened version of node
  194. ((node? value)
  195. (if (name-node? value)
  196. (name-node->variable value)
  197. (bug "bad definition value: ~S" value)))
  198. (else
  199. value)))
  200. (define name-node? (node-predicate 'name))
  201. (define (clean-sub-value! value)
  202. (cond ((pair? value)
  203. (let ((shared (car value)))
  204. (cond ((shared-shared? shared)
  205. (shared-variable shared))
  206. (else
  207. (set-car! value (clean-sub-value! (shared-saved shared)))
  208. (set-cdr! value (clean-sub-value! (cdr value)))
  209. value))))
  210. ((vector? value)
  211. (cond ((= 0 (vector-length value))
  212. value)
  213. ((shared-shared? (vector-ref value 0))
  214. (shared-variable (vector-ref value 0)))
  215. (else
  216. (vector-set! value 0 (clean-sub-value!
  217. (shared-saved (vector-ref value 0))))
  218. (do ((i 1 (+ i 1)))
  219. ((= i (vector-length value)))
  220. (vector-set! value i (clean-sub-value! (vector-ref value i))))
  221. value)))
  222. ((closure? value)
  223. (shared-variable (closure-temp value)))
  224. (else
  225. value)))
  226. (define (flatten-value value)
  227. (cond ((immutable? value)
  228. (flatten-immutable-value value))
  229. ((primitive? value)
  230. (primitive->name-node value))
  231. (else
  232. (flatten-value! value)
  233. value)))
  234. (define (flatten-value! value)
  235. (cond ((pair? value)
  236. (check-shared! (car value) flatten-pair! value))
  237. ((vector? value)
  238. (if (not (= 0 (vector-length value)))
  239. (check-shared! (vector-ref value 0) flatten-vector! value)))
  240. ((closure? value)
  241. (check-shared! (closure-temp value) flatten-closure! value))))
  242. (define (check-shared! shared flatten! value)
  243. (cond ((not (shared? shared))
  244. (flatten! value))
  245. ((not (shared-shared? shared))
  246. (set-shared-shared?! shared #t)
  247. (add-shared! value))))
  248. (define *immutable-value-table* #f)
  249. (define (flatten-immutable-value value)
  250. (cond ((pair? value)
  251. (or (shared-immutable-value value car)
  252. (let ((p (cons (car value) (cdr value))))
  253. (table-set! *immutable-value-table* value p)
  254. (flatten-pair! p)
  255. p)))
  256. ((vector? value)
  257. (if (= 0 (vector-length value))
  258. value
  259. (or (shared-immutable-value value (lambda (x) (vector-ref x 0)))
  260. (let ((v (copy-vector value)))
  261. (table-set! *immutable-value-table* value v)
  262. (flatten-vector! v)
  263. v))))
  264. ;; no immutable closures
  265. (else
  266. value))) ;; no sub-values
  267. (define (shared-immutable-value value accessor)
  268. (cond ((table-ref *immutable-value-table* value)
  269. => (lambda (copy)
  270. (cond ((not (shared-shared? (accessor copy)))
  271. (set-shared-shared?! (accessor copy) #t)
  272. (add-shared! copy)
  273. copy))))
  274. (else
  275. #f)))
  276. (define (flatten-pair! pair)
  277. (let ((temp (car pair))
  278. (shared (make-shared)))
  279. (set-car! pair shared)
  280. (set-shared-saved! shared (flatten-value temp))
  281. (set-cdr! pair (flatten-value (cdr pair)))))
  282. (define (flatten-vector! vector)
  283. (let ((temp (vector-ref vector 0))
  284. (shared (make-shared)))
  285. (vector-set! vector 0 shared)
  286. (set-shared-saved! shared (flatten-value temp))
  287. (do ((i 1 (+ i 1)))
  288. ((= i (vector-length vector)))
  289. (vector-set! vector i (flatten-value (vector-ref vector i))))))
  290. ;; Make top-level definitions for the bindings in the closure and then substitute
  291. ;; the defined variables within the closure's code. The define variables are
  292. ;; saved in the bindings in case they are shared with other closures (both for
  293. ;; efficiency and because SET! requires it).
  294. (define (flatten-closure! closure)
  295. (let ((shared (make-shared)))
  296. (for-each flatten-closure-binding! (closure-env closure))
  297. (set-closure-temp! closure shared)
  298. (set-shared-shared?! shared #t) ;; closures always need definitions
  299. (add-shared! closure)
  300. (receive (exp free)
  301. (substitute-in-expression (closure-node closure))
  302. (set-shared-saved! shared (cons exp free))
  303. (for-each clear-closure-binding! (closure-env closure)))))
  304. (define (clear-closure-binding! pair)
  305. (node-set! (car pair) 'substitute #f))
  306. ;; PAIR is (<name-node> . <value>) if it hasn't been seen before and
  307. ;; (<name-node> . <substitute-name-node>) if it has.
  308. (define (flatten-closure-binding! pair)
  309. (let* ((name (car pair))
  310. (subst (if (node? (cdr pair))
  311. (cdr pair)
  312. (let ((subst (make-name-node-subst name (cdr pair))))
  313. (set-cdr! pair subst)
  314. subst))))
  315. (node-set! name 'substitute subst)))
  316. (define (make-name-node-subst name value)
  317. (let ((var (add-package-definition! value (node-form name)))
  318. (subst (make-similar-node name (node-form name))))
  319. (node-set! subst 'binding (make-binding #f var #f))
  320. subst))
  321. (define op/literal (get-operator 'literal))
  322. (define op/name (get-operator 'name))
  323. ;;----------------------------------------------------------------
  324. (define *closed-compiled-primitives* #f)
  325. (define (make-primitive-node primitive call?)
  326. (if (and call?
  327. (primitive-expands-in-place? primitive))
  328. (make-node op/primitive primitive)
  329. (let ((name-node (primitive->name-node primitive)))
  330. (note-variable-use! (name-node->variable name-node))
  331. name-node)))
  332. (define (name-node->variable name-node)
  333. (let ((binding (node-ref name-node 'binding)))
  334. (cond ((not (binding? binding))
  335. (bug "unbound variable ~S" (node-form name-node)))
  336. ((primitive? (binding-static binding))
  337. (primitive->name-node (binding-static binding)))
  338. (else
  339. (binding-place binding)))))
  340. (define (primitive->name-node primitive)
  341. (let ((id (primitive-id primitive)))
  342. (or (table-ref *closed-compiled-primitives* id)
  343. (let* ((var (add-package-definition!
  344. (make-top-level-closure
  345. (expand (primitive-source primitive)
  346. prescheme-compiler-env))
  347. id))
  348. (binding (make-binding #f var #f))
  349. (node (make-node op/name id)))
  350. (node-set! node 'binding (make-binding #f var #f))
  351. (table-set! *closed-compiled-primitives* id node)
  352. (set-variable-flags! var (cons 'closed-compiled-primitive
  353. (variable-flags var)))
  354. node))))
  355. (define op/primitive (get-operator 'primitive))
  356. ;;----------------------------------------------------------------
  357. (define max-key-depth 5)
  358. ;; FIXME: review for collisions with string-hash
  359. (define (value-table-hash-function obj bound)
  360. (let recur ((obj obj) (depth 0))
  361. (cond ((= depth max-key-depth)
  362. 0)
  363. ((symbol? obj) (string-hash (symbol->string obj) bound))
  364. ((integer? obj)
  365. (if (< obj 0) (- -1 obj) obj))
  366. ((char? obj) (+ 333 (char->integer obj)))
  367. ((eq? obj #f) 3001)
  368. ((eq? obj #t) 3003)
  369. ((null? obj) 3005)
  370. ((pair? obj)
  371. (+ 3007
  372. (recur (car obj) (- depth 1))
  373. (* 3 (recur (cdr obj) (- depth 1)))))
  374. ((vector? obj)
  375. (let loop ((i 0) (hash (+ 3009 (vector-length obj))))
  376. (if (or (= i (vector-length obj))
  377. (= 0 (- depth i)))
  378. hash
  379. (loop (+ i 1) (+ hash (* i (recur (vector-ref obj i)
  380. (- depth i))))))))
  381. (else (error "value cannot be used as a table key" obj)))))
  382. (define make-value-table
  383. (make-hash-table eq? value-table-hash-function))