node-util.scm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  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/node/node-util.scm
  8. ;;;
  9. ;;; This file contains miscellaneous utilities for accessing and modifying the
  10. ;;; node tree.
  11. ;;;
  12. ;;; Get the root of the tree containing node.
  13. (define-module (ps-compiler node node-util)
  14. #:use-module (prescheme scheme48)
  15. #:use-module (ps-compiler node arch)
  16. #:use-module (ps-compiler node let-nodes)
  17. #:use-module (ps-compiler node node)
  18. #:use-module (ps-compiler node primop)
  19. #:use-module (ps-compiler node variable)
  20. #:use-module (ps-compiler param)
  21. #:use-module (ps-compiler util util)
  22. #:export (node-base containing-procedure
  23. trivial? nontrivial?
  24. nontrivial-ancestor
  25. calls-this-primop?
  26. bound-to-variable
  27. walk-refs-safely
  28. small-node?
  29. side-effects?
  30. called-node? called-node
  31. called-lambda
  32. get-lambda-value
  33. ;;set-reference?
  34. attach-call-args remove-call-args replace-call-args
  35. remove-null-arguments
  36. shorten-call-args insert-call-arg remove-call-arg
  37. append-call-arg
  38. remove-body
  39. attach-two-call-args
  40. attach-three-call-args
  41. attach-four-call-args
  42. attach-five-call-args
  43. remove-lambda-variable remove-variable remove-unused-variables
  44. substitute substitute-vars-in-node-tree
  45. replace-call-with-value
  46. copy-node-tree
  47. mark-ancestors marked-ancestor? unmarked-ancestor?
  48. node-ancestor? marked-ancestor least-common-ancestor
  49. proc-ancestor
  50. hoistable-node?
  51. find-scoping
  52. no-free-references?
  53. find-calls
  54. node-type
  55. the-undefined-value
  56. undefined-value?
  57. undefined-value-node?
  58. make-undefined-literal))
  59. (define (node-base node)
  60. (do ((p node (node-parent p)))
  61. ((not (node? (node-parent p)))
  62. p)))
  63. ;; Find the procedure node that contains NODE. Go up one parent at a time
  64. ;; until a lambda node is found, then go up two at a time, skipping the
  65. ;; intervening call nodes.
  66. (define (containing-procedure node)
  67. (do ((node (node-parent node) (node-parent node)))
  68. ((lambda-node? node)
  69. (do ((node node (node-parent (node-parent node))))
  70. ((proc-lambda? node) node)))))
  71. ;; Trivial calls are those whose parents are call nodes.
  72. (define (trivial? call)
  73. (call-node? (node-parent call)))
  74. (define (nontrivial? call)
  75. (lambda-node? (node-parent call)))
  76. (define (nontrivial-ancestor call)
  77. (let loop ((call call))
  78. (if (or (not (node? (node-parent call)))
  79. (nontrivial? call))
  80. call
  81. (loop (node-parent call)))))
  82. (define (calls-this-primop? call id)
  83. (eq? id (primop-id (call-primop call))))
  84. ;; Return the variable to which a value is bound by LET or LETREC.
  85. (define (bound-to-variable node)
  86. (let ((parent (node-parent node)))
  87. (case (primop-id (call-primop parent))
  88. ((let)
  89. (if (n= 0 (node-index node))
  90. (list-ref (lambda-variables (call-arg parent 0))
  91. (- (node-index node) 1))
  92. #f))
  93. ((letrec2)
  94. (if (< 1 (node-index node))
  95. (list-ref (lambda-variables
  96. (variable-binder
  97. (reference-variable (call-arg parent 1))))
  98. (- (node-index node) 1))
  99. #f))
  100. (else #f))))
  101. ;; Return a list of all the reference to lambda-node L's value that call it.
  102. ;; If not all can be identified then #F is returned.
  103. (define (find-calls l)
  104. (let ((refs (cond ((bound-to-variable l)
  105. => variable-refs)
  106. ((called-node? l)
  107. (list l))
  108. (else
  109. #f))))
  110. (cond ((and refs (every? called-node? refs))
  111. refs)
  112. ((calls-known? l)
  113. (bug "cannot find calls for known lambda ~S" l))
  114. (else #f))))
  115. ;; Walk (or map) a tree-modifying procedure down a variable's references.
  116. (define (walk-refs-safely proc var)
  117. (for-each proc (copy-list (variable-refs var))))
  118. ;; Return #t if the total primop-cost of NODE is less than SIZE.
  119. (define (small-node? node size)
  120. (let label ((call (lambda-body node)))
  121. (set! size (- size (primop-cost call)))
  122. (if (>= size 0)
  123. (walk-vector (lambda (n)
  124. (cond ((lambda-node? n)
  125. (label (lambda-body n)))
  126. ((call-node? n)
  127. (label n))))
  128. (call-args call))))
  129. (>= size 0))
  130. ;; True if executing NODE involves side-effects.
  131. (define (side-effects? node . permissible)
  132. (let ((permissible (cons #f permissible)))
  133. (let label ((node node))
  134. (cond ((not (call-node? node))
  135. #f)
  136. ((and (= 0 (call-exits node))
  137. (memq (primop-side-effects (call-primop node))
  138. permissible))
  139. (let loop ((i (- (call-arg-count node) 1)))
  140. (cond ((< i 0) #f)
  141. ((label (call-arg node i)) #t)
  142. (else (loop (- i 1))))))
  143. (else
  144. #t)))))
  145. ;; A conservative check - is there only one SET-CONTENTS call for the owner and
  146. ;; are all calls between CALL and the LETREC call that binds the owner calls to
  147. ;; SET-CONTENTS?
  148. ;;(define (single-letrec-set? call)
  149. ;; (let ((owner (call-arg call set/owner)))
  150. ;; (and (reference-node? owner)
  151. ;; (every? (lambda (ref)
  152. ;; (or (eq? (node-parent ref) call)
  153. ;; (not (set-reference? ref))))
  154. ;; (variable-refs (reference-variable owner))))))
  155. ;;(define (set-reference? node)
  156. ;; (and (eq? 'set-contents
  157. ;; (primop-id (call-primop (node-parent node))))
  158. ;; (= (node-index node) set/owner)))
  159. ;;-------------------------------------------------------------------------------
  160. (define the-undefined-value (list '*undefined-value*))
  161. (define (undefined-value? x)
  162. (eq? x the-undefined-value))
  163. (define (undefined-value-node? x)
  164. (and (literal-node? x)
  165. (undefined-value? (literal-value x))))
  166. (define (make-undefined-literal)
  167. (make-literal-node the-undefined-value #f))
  168. ;;-------------------------------------------------------------------------------
  169. ;; Finding the lambda node called by CALL, JUMP, or RETURN
  170. (define (called-node? node)
  171. (and (node? (node-parent node))
  172. (eq? node (called-node (node-parent node)))))
  173. (define (called-node call)
  174. (cond ((and (primop-procedure? (call-primop call))
  175. (primop-call-index (call-primop call)))
  176. => (lambda (i)
  177. (call-arg call i)))
  178. (else '#f)))
  179. (define (called-lambda call)
  180. (get-lambda-value (call-arg call (primop-call-index (call-primop call)))))
  181. (define (get-lambda-value value)
  182. (cond ((lambda-node? value)
  183. value)
  184. ((reference-node? value)
  185. (get-variable-lambda (reference-variable value)))
  186. (else
  187. (error "peculiar procedure in ~S" value))))
  188. (define (get-variable-lambda variable)
  189. (if (global-variable? variable)
  190. (or (variable-known-lambda variable)
  191. (error "peculiar procedure variable ~S" variable))
  192. (let* ((binder (variable-binder variable))
  193. (index (node-index binder))
  194. (call (node-parent binder))
  195. (lose (lambda ()
  196. (error "peculiar procedure variable ~S" variable))))
  197. (case (primop-id (call-primop call))
  198. ((let)
  199. (if (= 0 index)
  200. (get-lambda-value (call-arg call (+ 1 (variable-index variable))))
  201. (lose)))
  202. ((letrec1)
  203. (if (= 0 index)
  204. (get-letrec-variable-lambda variable)
  205. (lose)))
  206. ((call)
  207. (if (and (= 1 index)
  208. (= 0 (variable-index variable))) ;; var is a continuation var
  209. (get-lambda-value (call-arg call 0))
  210. (lose)))
  211. (else
  212. (lose))))))
  213. ;; Some of the checking can be removed once I know the LETREC code works.
  214. (define (get-letrec-variable-lambda variable)
  215. (let* ((binder (variable-binder variable))
  216. (call (lambda-body binder)))
  217. (if (and (eq? 'letrec2 (primop-id (call-primop call)))
  218. (reference-node? (call-arg call 1))
  219. (eq? (car (lambda-variables binder))
  220. (reference-variable (call-arg call 1))))
  221. (call-arg call (+ 1 (variable-index variable)))
  222. (error "LETREC is incorrectly organized ~S" (node-parent binder)))))
  223. ;;(define (get-cell-variable-lambda variable)
  224. ;; (let ((ref (first set-reference? (variable-refs variable))))
  225. ;; (if (and ref
  226. ;; (eq? 'letrec
  227. ;; (literal-value (call-arg (node-parent ref) set/type))))
  228. ;; (get-lambda-value (call-arg (node-parent ref) set/value))
  229. ;; (error "peculiar lambda cell ~S" variable))))
  230. ;;-------------------------------------------------------------------------------
  231. ;; Attaching and detaching arguments to calls
  232. ;; Make ARGS the arguments of call node PARENT. ARGS may contain #f.
  233. (define (attach-call-args parent args)
  234. (let ((len (call-arg-count parent)))
  235. (let loop ((args args) (i 0))
  236. (cond ((null? args)
  237. (if (< i (- len 1))
  238. (bug '"too few arguments added to node ~S" parent))
  239. (values))
  240. ((>= i len)
  241. (bug '"too many arguments added to node ~S" parent))
  242. (else
  243. (if (car args)
  244. (attach parent i (car args)))
  245. (loop (cdr args) (+ 1 i)))))))
  246. ;; Remove all of the arguments of NODE.
  247. (define (remove-call-args node)
  248. (let ((len (call-arg-count node)))
  249. (do ((i 1 (+ i 1)))
  250. ((>= i len))
  251. (if (not (empty? (call-arg node i)))
  252. (erase (detach (call-arg node i)))))
  253. (values)))
  254. ;; Replace the arguments of call node NODE with NEW-ARGS.
  255. (define (replace-call-args node new-args)
  256. (let ((len (length new-args)))
  257. (remove-call-args node)
  258. (if (n= len (call-arg-count node))
  259. (let ((new (make-vector len empty))
  260. (old (call-args node)))
  261. (set-call-args! node new)))
  262. (attach-call-args node new-args)))
  263. ;; Remove all arguments to CALL that are EMPTY?. COUNT is the number of
  264. ;; non-EMPTY? arguments.
  265. (define (remove-null-arguments call count)
  266. (let ((old (call-args call))
  267. (new (make-vector count empty)))
  268. (let loop ((i 0) (j 0))
  269. (cond ((>= j count)
  270. (values))
  271. ((not (empty? (vector-ref old i)))
  272. (set-node-index! (vector-ref old i) j)
  273. (vector-set! new j (vector-ref old i))
  274. (loop (+ i 1) (+ j 1)))
  275. (else
  276. (loop (+ i 1) j))))
  277. (set-call-args! call new)
  278. (values)))
  279. ;; Remove all but the first COUNT arguments from CALL.
  280. (define (shorten-call-args call count)
  281. (let ((old (call-args call))
  282. (new (make-vector count empty)))
  283. (vector-replace new old count)
  284. (do ((i (+ count 1) (+ i 1)))
  285. ((>= i (vector-length old)))
  286. (erase (vector-ref old i)))
  287. (set-call-args! call new)
  288. (values)))
  289. ;; Insert ARG as the INDEXth argument to CALL.
  290. (define (insert-call-arg call index arg)
  291. (let* ((old (call-args call))
  292. (len (vector-length old))
  293. (new (make-vector (+ 1 len) empty)))
  294. (vector-replace new old index)
  295. (do ((i index (+ i 1)))
  296. ((>= i len))
  297. (vector-set! new (+ i 1) (vector-ref old i))
  298. (set-node-index! (vector-ref old i) (+ i 1)))
  299. (set-call-args! call new)
  300. (attach call index arg)
  301. (values)))
  302. ;; Remove the INDEXth argument to CALL.
  303. (define (remove-call-arg call index)
  304. (let* ((old (call-args call))
  305. (len (- (vector-length old) 1))
  306. (new (make-vector len)))
  307. (vector-replace new old index)
  308. (if (node? (vector-ref old index))
  309. (erase (detach (vector-ref old index))))
  310. (do ((i index (+ i 1)))
  311. ((>= i len))
  312. (vector-set! new i (vector-ref old (+ i 1)))
  313. (set-node-index! (vector-ref new i) i))
  314. (set-call-args! call new)
  315. (if (< index (call-exits call))
  316. (set-call-exits! call (- (call-exits call) 1)))
  317. (values)))
  318. ;; Add ARG to the end of CALL's arguments.
  319. (define (append-call-arg call arg)
  320. (insert-call-arg call (call-arg-count call) arg))
  321. ;; Replace CALL with the body of its continuation.
  322. (define (remove-body call)
  323. (if (n= 1 (call-exits call))
  324. (bug "removing a call with ~D exits" (call-exits call))
  325. (replace-body call (detach-body (lambda-body (call-arg call 0))))))
  326. ;; Avoiding N-Ary Procedures
  327. ;; These are used in the expansion of the LET-NODES macro.
  328. (define (attach-two-call-args node a0 a1)
  329. (attach node 0 a0)
  330. (attach node 1 a1))
  331. (define (attach-three-call-args node a0 a1 a2)
  332. (attach node 0 a0)
  333. (attach node 1 a1)
  334. (attach node 2 a2))
  335. (define (attach-four-call-args node a0 a1 a2 a3)
  336. (attach node 0 a0)
  337. (attach node 1 a1)
  338. (attach node 2 a2)
  339. (attach node 3 a3))
  340. (define (attach-five-call-args node a0 a1 a2 a3 a4)
  341. (attach node 0 a0)
  342. (attach node 1 a1)
  343. (attach node 2 a2)
  344. (attach node 3 a3)
  345. (attach node 4 a4))
  346. ;;-------------------------------------------------------------------------------
  347. ;; Changing lambda-nodes' variable lists
  348. (define (remove-lambda-variable l-node index)
  349. (remove-variable l-node (list-ref (lambda-variables l-node) index)))
  350. (define (remove-variable l-node var)
  351. (if (used? var)
  352. (bug '"cannot remove referenced variable ~s" var))
  353. (erase-variable var)
  354. (let ((vars (lambda-variables l-node)))
  355. (if (eq? (car vars) var)
  356. (set-lambda-variables! l-node (cdr vars))
  357. (do ((vars vars (cdr vars)))
  358. ((eq? (cadr vars) var)
  359. (set-cdr! vars (cddr vars)))))))
  360. ;; Remove all of L-NODES' unused variables.
  361. (define (remove-unused-variables l-node)
  362. (set-lambda-variables! l-node
  363. (filter! (lambda (v)
  364. (cond ((used? v)
  365. #t)
  366. (else
  367. (erase-variable v)
  368. #f)))
  369. (lambda-variables l-node))))
  370. ;;------------------------------------------------------------------------------
  371. ;; Substituting Values For Variables
  372. ;; Substitute VAL for VAR. If DETACH? is true then VAL should be detached
  373. ;; and so can be used instead of a copy for the first substitution.
  374. ;;
  375. ;; If VAL is a reference to a variable named V, it was probably introduced by
  376. ;; the CPS conversion code. In that case, the variable is renamed with the
  377. ;; name of VAR. This helps considerably when debugging the compiler.
  378. (define (substitute var val detach?)
  379. (if (and (reference-node? val)
  380. (eq? 'v (variable-name (reference-variable val)))
  381. (not (global-variable? (reference-variable val))))
  382. (set-variable-name! (reference-variable val)
  383. (variable-name var)))
  384. (let ((refs (variable-refs var)))
  385. (set-variable-refs! var '())
  386. (cond ((not (null? refs))
  387. (for-each (lambda (ref)
  388. (replace ref (copy-node-tree val)))
  389. (if detach? (cdr refs) refs))
  390. (if detach? (replace (car refs) (detach val))))
  391. (detach?
  392. (erase (detach val))))))
  393. ;; Walk the tree NODE replacing references to variables in OLD-VARS with
  394. ;; the corresponding variables in NEW-VARS. Uses VARIABLE-FLAG to mark
  395. ;; the variables being replaced.
  396. (define (substitute-vars-in-node-tree node old-vars new-vars)
  397. (for-each (lambda (old new)
  398. (set-variable-flag! old new))
  399. old-vars
  400. new-vars)
  401. (let tree-walk ((node node))
  402. (cond ((lambda-node? node)
  403. (walk-vector tree-walk (call-args (lambda-body node))))
  404. ((call-node? node)
  405. (walk-vector tree-walk (call-args node)))
  406. ((and (reference-node? node)
  407. (variable-flag (reference-variable node)))
  408. => (lambda (new)
  409. (replace node (make-reference-node new))))))
  410. (for-each (lambda (old)
  411. (set-variable-flag! old #f))
  412. old-vars))
  413. ;; Replaces the call node CALL with VALUE.
  414. ;; (<proc> <exit> . <args>) => (<exit> <value>)
  415. (define (replace-call-with-value call value)
  416. (cond ((n= 1 (call-exits call))
  417. (bug '"can only substitute for call with one exit ~s" call))
  418. (else
  419. (let ((cont (detach (call-arg call 0))))
  420. (set-call-exits! call 0)
  421. (replace-call-args call (if value (list cont value) (list cont)))
  422. (set-call-primop! call (get-primop (enum primop-enum let)))))))
  423. ;;------------------------------------------------------------------------------
  424. ;; Copying Node Trees
  425. ;; Copy the node-tree NODE. This dispatches on the type of NODE.
  426. ;; Variables which have been copied have the copy in the node-flag field.
  427. (define (copy-node-tree node)
  428. (let ((new (cond ((lambda-node? node)
  429. (copy-lambda node))
  430. ((reference-node? node)
  431. (let ((var (reference-variable node)))
  432. (cond ((and (variable-binder var)
  433. (variable-flag var))
  434. => make-reference-node)
  435. (else
  436. (make-reference-node var)))))
  437. ((call-node? node)
  438. (copy-call node))
  439. ((literal-node? node)
  440. (copy-literal-node node)))))
  441. new))
  442. ;; Copy a lambda node and its variables. The variables' copies are put in
  443. ;; their VARIABLE-FLAG while the lambda's body is being copied.
  444. (define (copy-lambda node)
  445. (let* ((vars (map (lambda (var)
  446. (if var
  447. (let ((new (copy-variable var)))
  448. (set-variable-flag! var new)
  449. new)
  450. #f))
  451. (lambda-variables node)))
  452. (new-node (make-lambda-node (lambda-name node)
  453. (lambda-type node)
  454. vars)))
  455. (attach-body new-node (copy-call (lambda-body node)))
  456. (set-lambda-protocol! new-node (lambda-protocol node))
  457. (set-lambda-source! new-node (lambda-source node))
  458. (for-each (lambda (var)
  459. (if var (set-variable-flag! var #f)))
  460. (lambda-variables node))
  461. new-node))
  462. (define (copy-call node)
  463. (let ((new-node (make-call-node (call-primop node)
  464. (call-arg-count node)
  465. (call-exits node))))
  466. (do ((i 0 (+ i 1)))
  467. ((>= i (call-arg-count node)))
  468. (attach new-node i (copy-node-tree (call-arg node i))))
  469. (set-call-source! new-node (call-source node))
  470. new-node))
  471. ;;------------------------------------------------------------------------------
  472. ;; Checking the scoping of identifers
  473. ;; Mark all ancestors of N with FLAG
  474. (define (mark-ancestors n flag)
  475. (do ((n n (node-parent n)))
  476. ((not (node? n)) (values))
  477. (set-node-flag! n flag)))
  478. ;; Does N have an ancestor with a non-#f flag?
  479. (define (marked-ancestor? n)
  480. (do ((n n (node-parent n)))
  481. ((or (not (node? n))
  482. (node-flag n))
  483. (node? n))))
  484. ;; Does N have an ancestor with a #f flag?
  485. (define (unmarked-ancestor? n)
  486. (do ((n n (node-parent n)))
  487. ((or (not (node? n))
  488. (not (node-flag n)))
  489. (node? n))))
  490. ;; Is ANC? an ancestor of NODE?
  491. (define (node-ancestor? anc? node)
  492. (set-node-flag! anc? #t)
  493. (let ((okay? (marked-ancestor? node)))
  494. (set-node-flag! anc? #f)
  495. okay?))
  496. ;; Find the lowest ancestor of N that has a non-#f flag
  497. (define (marked-ancestor n)
  498. (do ((n n (node-parent n)))
  499. ((or (not (node? n))
  500. (node-flag n))
  501. (if (node? n) n #f))))
  502. ;; Mark the ancestors of START with #f, stopping when END is reached
  503. (define (unmark-ancestors-to start end)
  504. (do ((node start (node-parent node)))
  505. ((eq? node end))
  506. (set-node-flag! node #f)))
  507. ;; Return the lowest node that is above all NODES
  508. (define (least-common-ancestor nodes)
  509. (mark-ancestors (car nodes) #t)
  510. (let loop ((nodes (cdr nodes)) (top (car nodes)))
  511. (cond ((null? nodes)
  512. (mark-ancestors top #f)
  513. top)
  514. (else
  515. (let ((new (marked-ancestor (car nodes))))
  516. (unmark-ancestors-to top new)
  517. (loop (cdr nodes) new))))))
  518. ;; Can TO be moved to FROM without taking variables out of scope.
  519. ;; This first marks all of the ancestors of FROM, and then unmarks all of the
  520. ;; ancestors of TO. The net result is to mark every node that is above FROM but
  521. ;; not above TO. Then if any reference-node below FROM references a variable
  522. ;; with a marked binder, that node, and thus FROM itself, cannot legally be
  523. ;; moved to TO.
  524. ;; This is not currently used anywhere, and it doesn't know about trivial
  525. ;; calls.
  526. (define (hoistable-node? from to)
  527. (let ((from (if (call-node? from)
  528. (node-parent (nontrivial-ancestor from))
  529. from)))
  530. (mark-ancestors (node-parent from) #t)
  531. (mark-ancestors to #f)
  532. (let ((okay? (let label ((n from))
  533. (cond ((lambda-node? n)
  534. (let* ((vec (call-args (lambda-body n)))
  535. (c (vector-length vec)))
  536. (let loop ((i 0))
  537. (cond ((>= i c) #t)
  538. ((label (vector-ref vec i))
  539. (loop (+ i 1)))
  540. (else #f)))))
  541. ((reference-node? n)
  542. (let ((b (variable-binder (reference-variable n))))
  543. (or (not b) (not (node-flag b)))))
  544. (else #t)))))
  545. (mark-ancestors (node-parent from) #f)
  546. okay?)))
  547. ;; Mark all of the lambda nodes which bind variables referenced below NODE.
  548. (define (mark-binders node)
  549. (let label ((n node))
  550. (cond ((lambda-node? n)
  551. (walk-vector label (call-args (lambda-body n))))
  552. ((reference-node? n)
  553. (let ((b (variable-binder (reference-variable n))))
  554. (if b (set-node-flag! b #f))))))
  555. (values))
  556. ;;------------------------------------------------------------------------------
  557. ;; For each lambda-node L this sets (PARENT L) to be the enclosing PROC node
  558. ;; of L and, if L is a PROC node, sets (KIDS L) to be the lambda nodes it
  559. ;; encloses.
  560. (define (find-scoping lambdas parent set-parent! kids set-kids!)
  561. (receive (procs others)
  562. (partition-list proc-lambda? lambdas)
  563. (for-each (lambda (l)
  564. (set-parent! l #f)
  565. (set-kids! l '()))
  566. procs)
  567. (for-each (lambda (l)
  568. (set-parent! l #f))
  569. others)
  570. (letrec ((set-lambda-parent!
  571. (lambda (l)
  572. (cond ((parent l)
  573. => identity)
  574. ((proc-ancestor l)
  575. => (lambda (p)
  576. (let ((p (if (proc-lambda? p)
  577. p
  578. (set-lambda-parent! p))))
  579. (set-kids! p (cons l (kids p)))
  580. (set-parent! l p)
  581. p)))
  582. (else #f)))))
  583. (for-each set-lambda-parent! lambdas))
  584. (values procs others)))
  585. (define (proc-ancestor node)
  586. (let ((p (node-parent node)))
  587. (if (not (node? p))
  588. #f
  589. (let ((node (do ((p p (node-parent p)))
  590. ((lambda-node? p)
  591. p))))
  592. (do ((node node (node-parent (node-parent node))))
  593. ((proc-lambda? node)
  594. node))))))
  595. (define (no-free-references? node)
  596. (if (call-node? node)
  597. (error "NO-FREE-REFERENCES only works on value nodes: ~S" node))
  598. (let label ((node node))
  599. (cond ((reference-node? node)
  600. (let ((b (variable-binder (reference-variable node))))
  601. (or (not b)
  602. (node-flag b))))
  603. ((lambda-node? node)
  604. (set-node-flag! node #t)
  605. (let ((res (label (lambda-body node))))
  606. (set-node-flag! node #f)
  607. res))
  608. ((call-node? node)
  609. (let ((vec (call-args node)))
  610. (let loop ((i (- (vector-length vec) 1)))
  611. (cond ((< i 0) #t)
  612. ((not (label (vector-ref vec i))) #f)
  613. (else (loop (- i 1)))))))
  614. (else #t))))
  615. (define (node-type node)
  616. (cond ((literal-node? node)
  617. (literal-type node))
  618. ((reference-node? node)
  619. (variable-type (reference-variable node)))
  620. ((lambda-node? node)
  621. (lambda-node-type node))
  622. ((and (call-node? node)
  623. (primop-trivial? (call-primop node)))
  624. (trivial-call-return-type node))
  625. (else
  626. (error "node ~S does not represent a value" node))))
  627. ;;----------------------------------------------------------------
  628. ;; Debugging utilities
  629. (define (show-simplified node)
  630. (let loop ((n node) (r '()))
  631. (if (node? n)
  632. (loop (node-parent n) (cons (node-simplified? n) r))
  633. (reverse r))))
  634. (define (show-flag node)
  635. (let loop ((n node) (r '()))
  636. (if (node? n)
  637. (loop (node-parent n) (cons (node-flag n) r))
  638. (reverse r))))
  639. (define (reset-simplified node)
  640. (let loop ((n node))
  641. (cond ((node? n)
  642. (set-node-simplified?! n #f)
  643. (loop (node-parent n))))))