form.scm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  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. ;;; temporary hack
  8. ;;;(define enqueue! enqueue)
  9. ;;;(define dequeue! dequeue)
  10. (define-module (ps-compiler prescheme form)
  11. #:use-module (prescheme scheme48)
  12. #:use-module (prescheme s48-defrecord)
  13. #:use-module (prescheme record-discloser)
  14. #:use-module ((prescheme bcomp node) #:select (node? node-predicate) #:prefix bcomp-)
  15. #:use-module (ps-compiler front top)
  16. #:use-module (ps-compiler node let-nodes)
  17. #:use-module (ps-compiler node node)
  18. #:use-module (ps-compiler node node-equal)
  19. #:use-module (ps-compiler node node-util)
  20. #:use-module (ps-compiler node primop)
  21. #:use-module (ps-compiler node variable)
  22. #:use-module (ps-compiler node vector)
  23. #:use-module (ps-compiler prescheme primop primop)
  24. #:use-module (ps-compiler prescheme node-type)
  25. #:use-module (ps-compiler prescheme to-cps)
  26. #:use-module (ps-compiler prescheme type)
  27. #:use-module (ps-compiler prescheme type-scheme)
  28. #:use-module (ps-compiler prescheme type-var)
  29. #:use-module (ps-compiler simp simplify)
  30. #:use-module (ps-compiler util util)
  31. #:export (make-form
  32. form?
  33. form-value
  34. set-form-value!
  35. form-value-type
  36. set-form-value-type!
  37. node-form
  38. set-form-node!
  39. set-form-integrate!
  40. set-form-exported?!
  41. form-node
  42. form-var
  43. form-exported?
  44. form-type
  45. set-form-type!
  46. form-free set-form-free!
  47. suspend-form-use!
  48. use-this-form!
  49. also-use-this-form!
  50. set-form-lambdas!
  51. form-lambdas
  52. form-name
  53. form-merge set-form-merge!
  54. form-providers set-form-providers!
  55. form-clients set-form-clients!
  56. form-shadowed set-form-shadowed!
  57. variable-set!? note-variable-set!!
  58. make-form-unused!
  59. variable->form
  60. maybe-variable->form
  61. ;; high level stuff
  62. sort-forms
  63. expand-and-simplify-form
  64. remove-unreferenced-forms
  65. integrate-stob-form
  66. resimplify-form))
  67. (define-record-type form
  68. (var ;; variable being defined (if any)
  69. (value) ;; current value
  70. ;;source ;; one line of source code
  71. (free) ;; variables free in this form
  72. )
  73. (used? ;; is the value used in the program
  74. (exported? #f) ;; true if the definition in this form is exported
  75. (integrate 'okay) ;; one of OKAY, YES, NO, PARTIAL
  76. (aliases '()) ;; variables that are aliases for this one
  77. (shadowed '()) ;; package variables that should be shadowed here
  78. value-type ;; value's type
  79. (dependency-index #f) ;; index of this form in the data dependent order
  80. lambdas ;; list of all non-cont lambdas in this form
  81. (clients '()) ;; forms that use this one's variable
  82. (providers '()) ;; forms that define a variable used by this one
  83. (type #f) ;; one of LAMBDA, INTEGRATE, INITIALIZE or
  84. ;; #F for unfinished forms
  85. merge ;; slot used by form-merging code
  86. temp ;; handy slot
  87. ))
  88. (define-record-discloser type/form
  89. (lambda (form)
  90. `(form ,(variable-name (form-var form)))))
  91. (define (make-form var value free)
  92. (let ((form (form-maker var value free)))
  93. (if (maybe-variable->form var)
  94. (error "more than one definition of ~S" (variable-name var)))
  95. (set-variable-flags! var `((form . ,form) . ,(variable-flags var)))
  96. form))
  97. (define (pp-one-line x)
  98. (call-with-string-output-port
  99. (lambda (p)
  100. (write-one-line p 70 (lambda (p) (write x p))))))
  101. (define (form-node form)
  102. (let ((value (form-value form)))
  103. (if (node? value)
  104. value
  105. (bug "form's value is not a node ~S ~S" form value))))
  106. (define (set-form-node! form node lambdas)
  107. (set-node-flag! node form)
  108. (set-form-value! form node)
  109. (set-form-lambdas! form lambdas))
  110. (define (node-form node)
  111. (let ((form (node-flag (node-base node))))
  112. (if (form? form)
  113. form
  114. (bug "node ~S (~S) not in any form" node (node-base node)))))
  115. (define (suspend-form-use! form)
  116. (set-form-lambdas! form (make-lambda-list))
  117. (set-node-flag! (form-node form) form))
  118. (define (use-this-form! form)
  119. (initialize-lambdas)
  120. (also-use-this-form! form))
  121. (define (also-use-this-form! form)
  122. (add-lambdas (form-lambdas form))
  123. (set-node-flag! (form-node form) #f))
  124. (define (form-name form)
  125. (variable-name (form-var form)))
  126. (define (make-form-unused! form)
  127. (set-form-type! form 'unused)
  128. (cond ((node? (form-value form))
  129. (erase (form-value form))
  130. (set-form-value! form #f)
  131. (set-form-lambdas! form #f))))
  132. ;; notes on writing and reading forms
  133. ;; What we really need here are forms.
  134. ;; What to do? Can read until there are no missing lambdas = end of form
  135. ;; Need the variables as well.
  136. ;; (form index type var source? clients providers integrate?)
  137. ;; clients and providers are lists of indicies
  138. ;; can get lambdas automatically
  139. ;;(define (write-cps-file file forms)
  140. ;; (let ((port (make-tracking-output-port (open-output-file file))))
  141. ;; (reset-pp-cps)
  142. ;; (walk (lambda (f)
  143. ;; (write-form f port))
  144. ;; (sort-list forms
  145. ;; (lambda (f1 f2)
  146. ;; (< (form-index f1) (form-index f2)))))
  147. ;; (close-output-port port)))
  148. ;;(define (write-form form port)
  149. ;; (format port "(FORM ~D ~S ~S "
  150. ;; (form-index form)
  151. ;; (form-type form)
  152. ;; (form-integrate form))
  153. ;; (if (form-var form)
  154. ;; (print-variable-name (form-var form) port)
  155. ;; (format port "#f"))
  156. ;; (format port "~% ~S" (map form-index (form-clients form)))
  157. ;; (rereadable-pp-cps (form-value form) port)
  158. ;; (format port ")~%~%"))
  159. ;;------------------------------------------------------------------------------
  160. ;; Put the forms that do not reference any other forms' variables in a queue.
  161. ;; Every form gets a list of forms that use its variable and a list of forms
  162. ;; whose variables it uses.
  163. (define (sort-forms forms)
  164. (let ((queue (make-queue)))
  165. (for-each (lambda (f)
  166. (set-variable-flag! (form-var f) f))
  167. forms)
  168. (let ((forms (really-remove-unreferenced-forms
  169. forms
  170. set-providers-using-free)))
  171. (for-each (lambda (f)
  172. (if (null? (form-providers f))
  173. (enqueue! queue f)))
  174. (reverse forms))
  175. (for-each (lambda (f)
  176. (set-variable-flag! (form-var f) #f))
  177. forms)
  178. (values forms (make-form-queue queue forms)))))
  179. (define (set-providers-using-free form)
  180. (let loop ((vars (form-free form)) (provs '()))
  181. (cond ((null? vars)
  182. (set-form-providers! form provs))
  183. ((variable-flag (car vars))
  184. => (lambda (prov)
  185. (set-form-clients! prov (cons form (form-clients prov)))
  186. (loop (cdr vars) (cons prov provs))))
  187. (else
  188. (loop (cdr vars) provs)))))
  189. (define (make-form-queue ready forms)
  190. (let ((index 0))
  191. (lambda ()
  192. (let loop ()
  193. (cond ((not (queue-empty? ready))
  194. (let ((form (dequeue! ready)))
  195. (set-form-dependency-index! form index)
  196. (for-each (lambda (f)
  197. (set-form-providers! f (delq! form (form-providers f)))
  198. (if (and (null? (form-providers f))
  199. (not (form-dependency-index f))
  200. (form-used? f))
  201. (enqueue! ready f)))
  202. (form-clients form))
  203. (set! index (+ index 1))
  204. form))
  205. ((find-dependency-loop ready forms)
  206. => (lambda (rest)
  207. (set! forms rest)
  208. (loop)))
  209. (else #f))))))
  210. ;; Find a circular dependence between the remaining forms.
  211. (define (find-dependency-loop queue forms)
  212. (let ((forms (do ((forms forms (cdr forms)))
  213. ((or (null? forms)
  214. (not (form-dependency-index (car forms))))
  215. forms))))
  216. (cond ((null? forms)
  217. #f)
  218. (else
  219. ;;(format #t "Dependency loop!~%")
  220. (let ((form (really-find-dependency-loop forms)))
  221. (if (not (every? (lambda (f) (eq? 'no (form-integrate f)))
  222. (form-providers form)))
  223. (set-form-integrate! form 'no))
  224. (set-form-providers! form '())
  225. (enqueue! queue form)
  226. forms)))))
  227. (define (really-find-dependency-loop forms)
  228. (for-each (lambda (f) (set-form-temp! f #f))
  229. forms)
  230. (let label ((form (car forms)))
  231. (cond ((form-temp form)
  232. (break-dependency-loop (filter (lambda (f)
  233. (and (form-temp f) (form-var f)))
  234. forms)))
  235. (else
  236. (set-form-temp! form #t)
  237. (cond ((any-map label (form-providers form))
  238. => (lambda (res)
  239. (set-form-temp! form #f)
  240. res))
  241. (else
  242. (set-form-temp! form #f)
  243. #f))))))
  244. (define (any-map proc list)
  245. (let loop ((list list))
  246. (cond ((null? list)
  247. #f)
  248. ((proc (car list))
  249. => identity)
  250. (else
  251. (loop (cdr list))))))
  252. (define *loop-forms* #f)
  253. (define (break-dependency-loop forms)
  254. (or (first (lambda (f)
  255. (or (every? (lambda (f)
  256. (eq? 'no (form-integrate f)))
  257. (form-providers f))
  258. (memq? f (form-providers f))
  259. (and (bcomp-node? (form-value f))
  260. (bcomp-literal-node? (form-value f)))))
  261. forms)
  262. (begin (set! *loop-forms* forms)
  263. (let ((f (breakpoint "Break dependency loop: *loop-forms* = ~S" forms)))
  264. (set! *loop-forms* #f)
  265. f))))
  266. (define bcomp-literal-node?
  267. (bcomp-node-predicate 'literal))
  268. ;;----------------------------------------------------------------
  269. (define (variable-set!? var)
  270. (memq 'set! (variable-flags var)))
  271. (define (note-variable-set!! var)
  272. (if (not (variable-set!? var))
  273. (set-variable-flags! var (cons 'set! (variable-flags var)))))
  274. ;;------------------------------------------------------------------------------
  275. ;; Turn expression into nodes and simplify it.
  276. ;; Still to do:
  277. ;; Get representations of data values
  278. ;; Need to constant fold vector slots, including detection of modifications
  279. ;; and single uses.
  280. (define (expand-and-simplify-form form)
  281. (initialize-lambdas)
  282. (let* ((value (form-value form))
  283. (node (if (variable? value)
  284. (make-reference-node value)
  285. (x->cps (form-value form) (form-name form)))))
  286. (cond ((variable-set!? (form-var form))
  287. (set-form-type! form 'initialize)
  288. (set-form-node! form node '())
  289. "settable")
  290. ((reference-node? node)
  291. (let ((var (reference-variable node)))
  292. (add-known-form-value! form node)
  293. (cond ((maybe-variable->form var)
  294. => (lambda (f)
  295. (set-form-aliases! f
  296. `(,(form-var form)
  297. ,@(form-aliases form)
  298. . ,(form-aliases f))))))
  299. (set-form-type! form 'alias)
  300. (erase node)
  301. (set-form-value! form var)
  302. "alias"))
  303. ((literal-node? node)
  304. (expand-and-simplify-literal node form))
  305. ((lambda-node? node)
  306. (expand-and-simplify-lambda node form))
  307. (else
  308. (bug "funny form value ~S" node)))))
  309. ;; This could pay attention to immutability.
  310. (define (atomic? value)
  311. (not (or (vector? value)
  312. (pair? value))))
  313. (define (expand-and-simplify-literal node form)
  314. (let ((value (literal-value node)))
  315. (cond ((unspecific? value)
  316. (format #t "~%Warning: variable `~S' has no value and is not SET!~%"
  317. (form-name form))
  318. (set-form-value! form node)
  319. (set-form-lambdas! form '())
  320. (set-form-integrate! form 'no)
  321. (set-form-type! form 'unused)
  322. "constant")
  323. ((atomic? value)
  324. (add-known-form-value! form node)
  325. (set-form-value! form node)
  326. (set-form-lambdas! form '())
  327. "constant")
  328. (else
  329. (set-form-node! form (stob->node value) '())
  330. (set-form-type! form 'stob)
  331. "consed"))))
  332. ;; Make a call node containing the contents of the stob so that any
  333. ;; variables will be seen as referenced and any integrable values will
  334. ;; be integrated.
  335. ;; Only works for vectors at this point.
  336. ;; MAKE-VECTOR is a randomly chosen primop, almost anything could be used.
  337. (define (stob->node value)
  338. (let* ((contents '())
  339. (add! (lambda (x) (set! contents (cons x contents)))))
  340. (cond ((vector? value)
  341. (do ((i 0 (+ i 1)))
  342. ((>= i (vector-length value)))
  343. (add! (vector-ref value i))))
  344. (else
  345. (error "unknown kind of stob value ~S" value)))
  346. (let ((call (make-call-node (get-prescheme-primop 'make-vector)
  347. (+ 1 (length contents))
  348. 0))
  349. (node (make-lambda-node 'stob 'init '())))
  350. (attach call 0 (make-literal-node value #f)) ;; save for future use
  351. (do ((i 1 (+ i 1))
  352. (cs (reverse contents) (cdr cs)))
  353. ((null? cs))
  354. (let ((x (car cs)))
  355. (attach call i (if (variable? x)
  356. (make-reference-node x)
  357. (make-literal-node x type/unknown)))))
  358. (attach-body node call)
  359. (simplify-args call 1)
  360. node)))
  361. (define (add-known-form-value! form value)
  362. (let ((node (if (variable? value)
  363. (make-reference-node value)
  364. value))
  365. (var (form-var form)))
  366. (set-form-type! form 'integrate)
  367. (cond ((or (literal-node? node)
  368. (reference-node? node)
  369. (and (call-node? node)
  370. (trivial? node)))
  371. (add-variable-known-value! var (node->vector node))
  372. (if (variable? value)
  373. (erase node)))
  374. ((lambda-node? node)
  375. (add-variable-simplifier! var (make-inliner (node->vector node))))
  376. (else
  377. (bug "form's value ~S is not a value" value)))))
  378. (define (make-inliner vector)
  379. (lambda (call)
  380. (let ((proc (call-arg call 1)))
  381. (replace proc (reconstruct-value vector proc call)))))
  382. (define (reconstruct-value value proc call)
  383. (let ((has-type (maybe-follow-uvar (variable-type (reference-variable proc))))
  384. (node (vector->node value)))
  385. (if (type-scheme? has-type)
  386. (instantiate-type&value has-type node proc))
  387. node))
  388. (define (expand-and-simplify-lambda node form)
  389. (simplify-all node (form-name form))
  390. (let ((lambdas (make-lambda-list))
  391. (status (duplicate-form? form node)))
  392. (if status
  393. (add-known-form-value! form node))
  394. (set-form-node! form node lambdas)
  395. (set-form-type! form 'lambda)
  396. (set-form-free! form #f) ;; old value no longer valid
  397. status))
  398. (define *duplicate-lambda-size* 10)
  399. (define (set-duplicate-lambda-size! n)
  400. (set! *duplicate-lambda-size* n))
  401. (define (duplicate-form? form node)
  402. (cond ((or (variable-set!? (form-var form))
  403. (eq? 'no (form-integrate form)))
  404. #f)
  405. ((small-node? node *duplicate-lambda-size*)
  406. "small")
  407. ((eq? 'yes (form-integrate form))
  408. "by request")
  409. ;; ((called-arguments? node)
  410. ;; "called arguments")
  411. (else
  412. #f)))
  413. (define (called-arguments? node)
  414. (any? (lambda (v)
  415. (any? (lambda (n)
  416. (eq? n (called-node (node-parent n))))
  417. (variable-refs v)))
  418. (cdr (lambda-variables node))))
  419. ;;------------------------------------------------------------------------------
  420. (define (integrate-stob-form form)
  421. (if (and (eq? 'stob (form-type form))
  422. (elide-aliases! form)
  423. (not (form-exported? form))
  424. (every? cell-use (variable-refs (form-var form))))
  425. (let* ((var (form-var form))
  426. (ref (car (variable-refs var)))
  427. (call (lambda-body (form-value form))))
  428. ;; could fold any fixed references - do it later
  429. (cond ((and (null? (cdr (variable-refs var)))
  430. (called-node? (cell-use ref)))
  431. (format #t "computed-goto: ~S~%" (variable-name var))
  432. (make-computed-goto form))))))
  433. (define (cell-use node)
  434. (let ((parent (node-parent node)))
  435. (if (and (call-node? parent)
  436. (eq? 'vector-ref (primop-id (call-primop parent))))
  437. parent
  438. #f)))
  439. (define (elide-aliases! form)
  440. (not (or-map (lambda (f)
  441. (switch-references! (form-var f) (form-var form))
  442. (form-exported? f))
  443. (form-aliases form))))
  444. (define (switch-references! from to)
  445. (for-each (lambda (r)
  446. (set-reference-variable! r to))
  447. (variable-refs from))
  448. (set-variable-refs! to (append (variable-refs from) (variable-refs to))))
  449. ;;------------------------------------------------------------------------------
  450. (define (resimplify-form form)
  451. (let ((node (form-value form)))
  452. (cond ((and (node? node)
  453. (not (eq? 'stob (form-type form)))
  454. (not (node-simplified? node)))
  455. (use-this-form! form)
  456. (simplify-node node)
  457. (suspend-form-use! form)))))
  458. ;;------------------------------------------------------------------------------
  459. ;; This is removes all forms that are not ultimately referenced from some
  460. ;; exported form.
  461. (define (add-form-provider! form provider)
  462. (if (not (memq? provider (form-providers form)))
  463. (set-form-providers!
  464. form
  465. (cons provider (form-providers form)))))
  466. (define (variable->form var)
  467. (or (maybe-variable->form var)
  468. (bug "variable ~S has no form" var)))
  469. (define (maybe-variable->form var)
  470. (cond ((flag-assq 'form (variable-flags var))
  471. => cdr)
  472. (else
  473. #f)))
  474. (define (remove-unreferenced-forms forms)
  475. (really-remove-unreferenced-forms forms set-form-providers))
  476. (define (really-remove-unreferenced-forms forms set-form-providers)
  477. (receive (exported others)
  478. (partition-list form-exported? forms)
  479. (for-each (lambda (f)
  480. (set-form-providers! f '())
  481. (set-form-clients! f '())
  482. (set-form-used?! f (form-exported? f)))
  483. forms)
  484. (for-each set-form-providers forms)
  485. (propogate-used?! exported)
  486. (append (remove-unused-forms others) exported)))
  487. (define (set-form-providers form)
  488. (for-each (lambda (n)
  489. (add-form-provider! (node-form n) form))
  490. (variable-refs (form-var form)))
  491. (if (eq? (form-type form) 'alias)
  492. (add-form-provider! form (variable->form (form-value form)))))
  493. (define (propogate-used?! forms)
  494. (let loop ((to-do forms))
  495. (if (not (null? to-do))
  496. (let loop2 ((providers (form-providers (car to-do)))
  497. (to-do (cdr to-do)))
  498. (if (null? providers)
  499. (loop to-do)
  500. (loop2 (cdr providers)
  501. (let ((p (car providers)))
  502. (cond ((form-used? p)
  503. to-do)
  504. (else
  505. (set-form-used?! p #t)
  506. (cons p to-do))))))))))
  507. ;; Actually remove forms that are not referenced.
  508. (define (remove-unused-forms forms)
  509. ;; (format #t "Removing unused forms~%")
  510. (filter (lambda (f)
  511. (cond ((or (not (form-used? f))
  512. )
  513. ;;(let ((value (form-value f)))
  514. ;; (and (quote-exp? value)
  515. ;; (external-value? (quote-exp-value value))))
  516. ;; (format #t " ~S~%" (variable-name (form-var f)))
  517. (erase-variable (form-var f))
  518. (cond ((node? (form-value f))
  519. (erase (form-value f))
  520. (set-form-value! f #f)
  521. (set-form-lambdas! f '())))
  522. #f)
  523. (else #t)))
  524. forms))
  525. ;;------------------------------------------------------------
  526. ;; Total yucko.
  527. ;; (unknown-call (lambda e-vars e-body)
  528. ;; protocol
  529. ;; (vector-ref x offset)
  530. ;; . args)
  531. ;; =>
  532. ;; (let (lambda ,vars
  533. ;; (computed-goto
  534. ;; ...
  535. ;; (lambda ()
  536. ;; (unknown-call (lambda ,copied-evars
  537. ;; (jump ,(car vars) ,copied-evars))
  538. ;; ,(vector-ref proc-vector i)
  539. ;; . ,(cdr vars)))
  540. ;; ...
  541. ;; '((offsets ...) ...) ; offsets for each continuation
  542. ;; ,offset))
  543. ;; ,exit
  544. ;; . ,args)
  545. (define (make-computed-goto form)
  546. (let* ((ref (car (variable-refs (form-var form))))
  547. (in-form (node-form ref))
  548. (entries (vector->offset-map (call-args (lambda-body (form-node form))))))
  549. (use-this-form! in-form)
  550. (also-use-this-form! form)
  551. (really-make-computed-goto (node-parent ref) entries)
  552. (erase (form-node form))
  553. (set-form-value! form #f)
  554. (set-form-lambdas! form #f)
  555. (simplify-node (form-node in-form))
  556. (suspend-form-use! in-form)))
  557. ;; Returns a list ((<node> . <offsets>) ...) where <offsets> are where <node>
  558. ;; was found in VECTOR. The first element of VECTOR is a marker which we
  559. ;; pretend isn't there.
  560. ;;
  561. ;; This would be more effective if done by a simplifier after the continuations
  562. ;; had been simplified.
  563. (define (vector->offset-map vector)
  564. (let loop ((i 0) (res '()))
  565. (if (= (+ i 1) (vector-length vector))
  566. (reverse (map (lambda (p)
  567. (cons (car p) (reverse (cdr p))))
  568. res))
  569. (let ((n (vector-ref vector (+ i 1))))
  570. (loop (+ i 1)
  571. (cond ((first (lambda (p)
  572. (node-equal? n (car p)))
  573. res)
  574. => (lambda (p)
  575. (set-cdr! p (cons i (cdr p)))
  576. res))
  577. (else
  578. (cons (list n i) res))))))))
  579. (define (really-make-computed-goto vec-ref entries)
  580. (let* ((exits (length entries))
  581. (offset (call-arg vec-ref 1))
  582. (vector-call (node-parent vec-ref))
  583. (args (sub-vector->list (call-args vector-call) 3))
  584. (call (make-call-node (get-prescheme-primop 'computed-goto)
  585. (+ 2 exits)
  586. exits))
  587. (arg-vars (map (lambda (arg) (make-variable 't (node-type arg)))
  588. args))
  589. (protocol (literal-value (call-arg vector-call 2)))
  590. (cont (call-arg vector-call 0)))
  591. (for-each detach args)
  592. (attach call exits (make-literal-node (map cdr entries) #f))
  593. (attach call (+ exits 1) (detach offset))
  594. (receive (top continuations)
  595. (if (reference-node? cont)
  596. (make-computed-goto-tail-conts call args arg-vars entries cont protocol)
  597. (make-computed-goto-conts call args arg-vars entries cont protocol))
  598. (do ((i 0 (+ i 1))
  599. (l continuations (cdr l)))
  600. ((= i exits))
  601. (attach call i (car l)))
  602. (replace-body vector-call top))))
  603. (define (make-computed-goto-tail-conts call args arg-vars entries cont protocol)
  604. (let-nodes ((top (let 1 l1 . args))
  605. (l1 arg-vars call))
  606. (values top (map (lambda (p)
  607. (computed-goto-tail-exit
  608. (detach (car p))
  609. protocol
  610. (reference-variable cont)
  611. arg-vars))
  612. entries))))
  613. (define (computed-goto-tail-exit node protocol cont-var arg-vars)
  614. (let ((args (map make-reference-node arg-vars)))
  615. (let-nodes ((l1 () (unknown-tail-call 0 (* cont-var)
  616. node
  617. '(protocol #f) . args)))
  618. l1)))
  619. (define (make-computed-goto-conts call args arg-vars entries cont protocol)
  620. (let ((cont-vars (lambda-variables cont))
  621. (cont-type (make-arrow-type (map variable-type
  622. (lambda-variables cont))
  623. type/null)))
  624. (detach cont)
  625. (change-lambda-type cont 'jump)
  626. (let-nodes ((top (let 1 l1 cont . args))
  627. (l1 ((j cont-type) . arg-vars) call))
  628. (values top
  629. (map (lambda (p)
  630. (computed-goto-exit (detach (car p))
  631. protocol
  632. arg-vars
  633. j
  634. cont-vars))
  635. entries)))))
  636. (define (computed-goto-exit node protocol arg-vars cont-var cont-vars)
  637. (let* ((cont-vars (map copy-variable cont-vars))
  638. (cont-args (map make-reference-node cont-vars))
  639. (args (map make-reference-node arg-vars)))
  640. (let-nodes ((l1 () (unknown-call 1 l2 node '(protocol #f) . args))
  641. (l2 cont-vars (jump 0 (* cont-var) . cont-args)))
  642. l1)))