jinx-cselim.scm 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;; -*- Scheme -*-
  21. (declare (usual-integrations))
  22. ;; $Header: expr.scm,v 1.13 90/09/22 16:37:09 GMT jinx Exp $
  23. #|
  24. *** To do: ***
  25. - Cselim is done on expressions and an optional list of special
  26. operators with reordering properties be provided. The notion
  27. of a variable being an operator is not inherent in the expression,
  28. but only part of constant-folding and cse-ing.
  29. - Improve cselim to handle some (or all) of the cases that are
  30. specified there.
  31. - Improve the reordering capabilities of cse so that if the operators
  32. are not associative, it won't do the wrong thing, but will still
  33. assume commutativity, for example.
  34. - Implement constant folder.
  35. Takes a list of bindings of free variables and procedures to use.
  36. - Use tables in bind to merge global variables, etc.
  37. Perhaps even collect the global environment in expressions rather
  38. than a list of global variables. Or collect with names.
  39. We seem to be continually recomputing assq lists only to throw them
  40. out again at the end.
  41. - Expression equality should treat operators differently, since abelian
  42. ones allow other orderings. This is painful, but should be done.
  43. - To fix in expression/bind:
  44. Binding a free variable to a lambda expression should beta-reduce
  45. any combinations where the free variable is the operator.
  46. - To fix in expression/combine:
  47. If operator is lambda expression, it should beta-reduce.
  48. |#
  49. ;;;; Common text utility.
  50. (define* (text/cselim text #:optional operators)
  51. ;; (expression->text (expression/cselim (text->expression text)))
  52. ;; Like ^ but avoids copying.
  53. (let ((lam (lam/make false)))
  54. (fluid-let ((*warn-body?* *allow-warnings?*)
  55. (*global-lam* lam)
  56. (*global-env* (table+/make))
  57. (*global-vars* '())
  58. (*constants* '()))
  59. (expression->graph text)
  60. (collect-input-set! (lam/node *global-lam*))
  61. (fluid-let ((*operators*
  62. (process-operators
  63. (if (default-object? operators)
  64. *standard-operators*
  65. operators))))
  66. (grow-subexpressions! (lam/node *global-lam*)))
  67. (if *recompute-input-sets?*
  68. (collect-input-set! (lam/node *global-lam*)))
  69. (sort-subexpressions! (lam/node *global-lam*))
  70. (if *alpha-rename-lazily?*
  71. (alpha-rename! (lam/node *global-lam*)))
  72. (graph->expression (lam/node *global-lam*)))))
  73. ;;;; Top level
  74. ;;; Coercions and other operations.
  75. (define (text->expression text)
  76. (let ((lam (lam/make false)))
  77. (fluid-let ((*warn-body?* *allow-warnings?*)
  78. (*global-lam* lam)
  79. (*global-env* (table+/make))
  80. (*global-vars* '())
  81. (*constants* '()))
  82. (expression->graph text)
  83. (collect-input-set! (lam/node *global-lam*))
  84. (collect-expression))))
  85. (define (expression->text expression)
  86. (with-copied-expression expression
  87. (lambda ()
  88. (if *recompute-input-sets?*
  89. (collect-input-set! (lam/node *global-lam*)))
  90. (sort-subexpressions! (lam/node *global-lam*))
  91. (if *alpha-rename-lazily?*
  92. (alpha-rename! (lam/node *global-lam*)))
  93. (graph->expression (lam/node *global-lam*)))))
  94. (define (expression/pp expression)
  95. (pp (expression->text expression)
  96. (current-output-port)
  97. true))
  98. (define (expression/copy expression)
  99. (fluid-let ((*associations* (table+/make)))
  100. (%expression/copy expression)))
  101. (define (expression/equal? expression1 expression2)
  102. (fluid-let ((*associations* (table+/make))
  103. (*reverse-associations* (table+/make)))
  104. (%expression/equal? expression1 expression2)))
  105. ;;; Higher level operations
  106. (define* (expression/cselim expression #:optional operators)
  107. (with-copied-expression expression
  108. (lambda ()
  109. (fluid-let ((*operators*
  110. (process-operators
  111. (if (default-object? operators)
  112. *standard-operators*
  113. operators))))
  114. (grow-subexpressions! (lam/node *global-lam*))
  115. (collect-expression)))))
  116. ;; These just need to check the global variables.
  117. (define (expression/free? expression name)
  118. (there-exists? (expression/variables expression)
  119. (lambda (node)
  120. (eq? name (var-node/name node)))))
  121. (define (expression/free-variables expression)
  122. (%map-1 var-node/name
  123. (expression/variables expression)))
  124. ;;;; Top level operations (continued)
  125. (define* (lambda-expression->procedure expression #:optional environment)
  126. (eval (expression->text expression)
  127. (if (default-object? environment)
  128. (nearest-repl/environment)
  129. environment)))
  130. (define (expression/rename expression renames)
  131. ;; Renames is a list of lists each containing an old name and a new name.
  132. ;; This is like expression/bind where the values are simple variable
  133. ;; nodes, but cheaper.
  134. (with-no-conflicting-variables
  135. expression
  136. (lambda ()
  137. (for-each
  138. (lambda (global-var)
  139. (let ((place (assq (var-node/name node) renames)))
  140. (if place
  141. (set-var-node/name! global-var (cadr place)))))
  142. *global-vars*))))
  143. (define (expression/bind expression bindings)
  144. #| ;
  145. ;; bindings is a list of lists each containing a name and a
  146. ;; value (another expression). Essentially equivalent to
  147. (text->expression
  148. `(LET (,@(%map-1 (lambda (binding)
  149. (list (car binding)
  150. (expression->text (cadr binding))))
  151. bindings))
  152. ,(expression->text expression)))
  153. |#
  154. #| ;
  155. ;; Eliminate useless bindings.
  156. (let ((bindings
  157. (let ((free-vars (expression/free-variables expression)))
  158. (list-transform-positive
  159. bindings
  160. (lambda (binding)
  161. (memq (car binding) free-vars))))))
  162. (if (null? bindings)
  163. expression
  164. (fluid-let ((*associations* (table+/make)))
  165. (let ((expr* (%expression/bind expression bindings)))
  166. (collect-input-set! (expression/node expr*))
  167. expr*))))
  168. |#
  169. ;; For now, until lambda expressions are processed correctly.
  170. ;; The second text->expression, etc. is to handle the case
  171. ;; where the LET binds lambdas.
  172. ;; *** This is a kludge! ***
  173. (text->expression
  174. (expression->text
  175. (text->expression
  176. `(LET (,@(%map-1 (lambda (binding)
  177. (list (car binding)
  178. (expression->text (cadr binding))))
  179. bindings))
  180. ,(expression->text expression))))))
  181. ;;;; Top level operations (continued)
  182. (define (expression/capture expression parameter-names)
  183. #|
  184. ;; This binds parameter-names. If any are free in expression,
  185. ;; they are removed from the free list. Essentially equivalent to
  186. (text->expression
  187. `(LAMBDA ,parameter-names
  188. ,(expression->text expression)))
  189. |#
  190. (with-copied-expression
  191. expression
  192. (lambda ()
  193. (let* ((global-lam* (lam/make false))
  194. (params
  195. (let ((names&nodes
  196. (%map-1 (lambda (node)
  197. (set-var-node/lam! node global-lam*)
  198. (cons (var-node/name node)
  199. node))
  200. *global-vars*)))
  201. (%map-1
  202. (lambda (name)
  203. (or (assq name names&nodes)
  204. (cons name
  205. (let ((node
  206. (node/make 'INPUT 'VARIABLE
  207. (var/make name global-lam*))))
  208. (set-node/input-set! node (list node))
  209. node))))
  210. parameter-names))))
  211. (let ((lam *global-lam*)
  212. (node (lam/node *global-lam*))
  213. (params (%map-1 cdr params)))
  214. (let ((node* (node/make 'REDUCIBLE 'LAMBDA global-lam*
  215. (list node)))
  216. (global-vars*
  217. (eq-set/difference *global-vars* params)))
  218. (set-node/parents! node (list node*))
  219. (set-node/input-set! node global-vars*)
  220. (set-lam/params! lam params)
  221. (set-lam/body! global-lam* node)
  222. (set-lam/node! global-lam* node*)
  223. (for-each (lambda (param)
  224. (set-var-node/lam! param lam))
  225. params)
  226. (expression/make true *constants*
  227. global-vars* global-lam*)))))))
  228. (define (expression/combine oprtrexp operandexps)
  229. ;; *** Handle combining a lambda expression! ***
  230. #|
  231. ;; Essentially
  232. (text->expression
  233. (cons (expression->text oprtrexp)
  234. (%map-1 expression->text operandexps)))
  235. |#
  236. #|
  237. (fluid-let ((*associations* (table+/make)))
  238. (let ((expr* (%unify-1 (cons oprtrexp operandexps))))
  239. (%unify-2 expr*
  240. (node/make 'REDUCIBLE 'COMBINATION
  241. false
  242. (cons (expression/body oprtrexp)
  243. (%map-1 expression/body operandexps))))
  244. expr*))
  245. |#
  246. ;; For now, until lambda expressions are handled
  247. (text->expression
  248. (cons (expression->text oprtrexp)
  249. (%map-1 expression->text operandexps)))
  250. )
  251. ;;;; Top level operations (continued)
  252. ;; This assumes that no node is a child^n of itself.
  253. ;; letrec will make this fail!
  254. ;; *** If we write something like Y, will it fail? ***
  255. (define (expression/walk expression recvr)
  256. (let ((context (context/make))
  257. (expr (expression/copy expression)))
  258. (if (not (expression/lazy-rename? expr))
  259. (alpha-rename! (expression/node expr)))
  260. (recvr
  261. context
  262. (expression/body expr)
  263. (lambda (node node-processor)
  264. (let walk-node ((node node))
  265. (let* ((table (context/result-cache context))
  266. (result (table+/association table node)))
  267. (cond ((not result)
  268. (table+/associate! table node 'WALKING)
  269. (let ((result* (node-processor node walk-node)))
  270. (if (not (eq? (table+/association table node) 'WALKING))
  271. (error "expression/process: Multiple results" node)
  272. (begin
  273. (table+/associate! table node (list result*))
  274. result*))))
  275. ((eq? result 'WALKING)
  276. (error "expression/process: Circularity found" node))
  277. (else
  278. (car result)))))))))
  279. ;;;; Top level: utilities and state variables.
  280. (define *allow-warnings?* true)
  281. ;; If the following two are set to true, the program will rename the
  282. ;; least number of variables to avoid conflicts. Any other
  283. ;; combination will be faster, but will rename more variables.
  284. (define *recompute-input-sets?* true)
  285. (define *alpha-rename-lazily?* true)
  286. (define *standard-operators*
  287. `((+ ABELIAN-GROUP 0 -)
  288. (* ABELIAN-GROUP 1 /)
  289. (- ABELIAN-GROUP-INVERSE 0 +)
  290. (/ ABELIAN-GROUP-INVERSE 1 *)))
  291. (define *warn-body?*)
  292. (define *operators*)
  293. (define *global-lam*)
  294. (define *global-env*)
  295. (define *global-vars*)
  296. (define *constants*)
  297. (define *associations*)
  298. (define *reverse-associations*)
  299. (define-integrable (collect-expression)
  300. (expression/make *alpha-rename-lazily?*
  301. *constants*
  302. *global-vars*
  303. *global-lam*))
  304. (define (with-expression expression thunk)
  305. (fluid-let ((*alpha-rename-lazily?* (expression/lazy-rename? expression))
  306. (*constants* (expression/constants expression))
  307. (*global-vars* (expression/variables expression))
  308. (*global-lam* (expression/graph expression)))
  309. (thunk)))
  310. (define (with-copied-expression expression thunk)
  311. (with-expression (expression/copy expression)
  312. thunk))
  313. ;; This forces to lazy-rename? since otherwise
  314. ;; things would have to be renamed now.
  315. (define (with-no-conflicting-variables expression recvr)
  316. (with-copied-expression
  317. (if (expression/lazy-rename? expression)
  318. expression
  319. (expression/make true
  320. (expression/constants expression)
  321. (expression/variables expression)
  322. (expression/graph expression)))
  323. recvr))
  324. ;;;; Data structures
  325. (define-structure (j-expression
  326. (conc-name expression/)
  327. (print-procedure
  328. (lambda (state node)
  329. (structure/unparse
  330. state node
  331. expression-unparse-fields
  332. false)))
  333. (constructor expression/make))
  334. (lazy-rename? false read-only true)
  335. (constants '() read-only true)
  336. (variables '() read-only true)
  337. (graph false read-only true))
  338. (define expression-unparse-fields
  339. `("expression" ("lazy-rename?" ,expression/lazy-rename?)
  340. ("graph" ,expression/graph)))
  341. (define-integrable (expression/body expr)
  342. (lam/body (expression/graph expr)))
  343. (define-integrable (expression/node expr)
  344. (lam/node (expression/graph expr)))
  345. (define-structure (context
  346. (conc-name context/)
  347. (print-procedure
  348. (lambda (state node)
  349. (structure/unparse
  350. state node
  351. context-unparser-fields
  352. false)))
  353. (constructor context/make ()))
  354. (constants (table+/make) read-only true)
  355. (free-vars (table+/make) read-only true)
  356. (bound-vars (table+/make) read-only true)
  357. (result-cache (table+/make) read-only true))
  358. (define context-unparser-fields
  359. `("context"
  360. #|
  361. ("constants" ,context/constants)
  362. ("free-vars" ,context/free-vars)
  363. ("bound-vars" ,context/bound-vars)
  364. ("result-cache" ,context/result-cache)
  365. |#
  366. ))
  367. ;;;; Data structures (continued)
  368. (define-structure (node (conc-name node/)
  369. (print-procedure
  370. (lambda (state node)
  371. (structure/unparse
  372. state node
  373. node-unparse-fields
  374. false)))
  375. (constructor
  376. node/make
  377. (type1 type2 extra #:optional children)))
  378. (type1 false read-only true)
  379. (type2 false read-only true)
  380. ;; This field is conceptually never changed, but copy-node needs it to
  381. ;; be mutable to avoid infinite recursion.
  382. (extra false read-only false)
  383. (children '() read-only false)
  384. (parents '() read-only false)
  385. (input-set '() read-only false)
  386. (generation 0 read-only false)
  387. (name false read-only false)
  388. ;; Used locally to avoid processing twice.
  389. (mark false read-only false))
  390. (define node-unparse-fields
  391. `("node" ("type1" ,node/type1)
  392. ("type2" ,node/type2)
  393. ("extra" ,node/extra)
  394. #|
  395. ("children" ,node/children)
  396. ("parents" ,node/parents)
  397. ("input-set" ,node/input-set)
  398. |#
  399. ))
  400. (define-integrable (node/type node)
  401. (node/type2 node))
  402. (define-structure (var (conc-name var/)
  403. (print-procedure
  404. (lambda (state var)
  405. (structure/unparse
  406. state var
  407. var-unparse-fields
  408. false)))
  409. (constructor var/make (name lam)))
  410. (name false read-only false)
  411. (lam false read-only false))
  412. (define var-unparse-fields
  413. `("var" ("name" ,var/name)
  414. ("lam" ,var/lam)))
  415. (define-integrable (var-node/name var)
  416. (var/name (node/extra var)))
  417. (define-integrable (set-var-node/name! var name)
  418. (set-var/name! (node/extra var) name))
  419. (define-integrable (var-node/lam var)
  420. (var/lam (node/extra var)))
  421. (define-integrable (set-var-node/lam! var lam)
  422. (set-var/lam! (node/extra var) lam))
  423. ;;;; Data structures (continued)
  424. (define-structure (lam (conc-name lam/)
  425. (print-procedure
  426. (lambda (state lam)
  427. (structure/unparse
  428. state lam
  429. lam-unparse-fields
  430. false)))
  431. (constructor lam/make (parent)))
  432. (parent false read-only false)
  433. (params '() read-only false)
  434. (body false read-only false)
  435. (node false read-only false)
  436. (aux false read-only false)
  437. (text false read-only false))
  438. (define lam-unparse-fields
  439. `("lam" ("parent" ,lam/parent)
  440. ("params" ,lam/params)
  441. ("body" ,lam/body)
  442. ("node" ,lam/node)
  443. ("aux" ,lam/aux)))
  444. (define-integrable (lam-node/params lam)
  445. (lam/params (node/extra lam)))
  446. (define-integrable (lam-node/body lam)
  447. (lam/body (node/extra lam)))
  448. (define-integrable (set-lam-node/body! lam body)
  449. (set-lam/body! (node/extra lam) body))
  450. (define-integrable (lam-node/aux lam)
  451. (lam/aux (node/extra lam)))
  452. (define-integrable (global-lam/make)
  453. (lam/make false))
  454. (define-integrable (global-lam? lam)
  455. (false? (lam/parent lam)))
  456. (define-integrable (constant-node/value lit)
  457. (node/extra lit))
  458. ;;;; Input processor
  459. (define (expression->graph expression)
  460. (lambda-body->graph *global-lam* '() '() '() expression))
  461. (define (->graph expression environment olam)
  462. (cond ((pair? expression)
  463. (case (car expression)
  464. ((LET*)
  465. (->graph (canonicalize-let* expression)
  466. environment
  467. olam))
  468. ((LET)
  469. (let->graph expression environment olam))
  470. ((LAMBDA)
  471. (lambda->graph expression environment olam))
  472. (else
  473. (if (lambda-combination? expression)
  474. (->graph (canonicalize-lambda-combination expression)
  475. environment
  476. olam)
  477. (combination->graph expression environment olam)))))
  478. ((variable? expression)
  479. (var->graph expression environment olam))
  480. (else
  481. (constant->graph expression environment olam))))
  482. ;;; Special handlers
  483. (define (constant->graph expression environment olam)
  484. environment olam ; ignored
  485. (let ((place (assv expression *constants*)))
  486. (if place
  487. (cdr place)
  488. (let ((new (node/make 'INPUT 'CONSTANT expression)))
  489. (set! *constants*
  490. (cons (cons expression new)
  491. *constants*))
  492. new))))
  493. ;;;; Input processor: special handlers (continued)
  494. (define (var->graph name environment olam)
  495. olam ; ignored
  496. (cond ((j-lookup environment name))
  497. ((table+/association *global-env* name))
  498. (else
  499. (add-global-variable! name
  500. (node/make 'INPUT 'VARIABLE
  501. (var/make name *global-lam*))))))
  502. (define (add-global-variable! name node)
  503. (table+/associate! *global-env* name node)
  504. (set! *global-vars* (cons node *global-vars*))
  505. node)
  506. (define (let->graph expression environment olam)
  507. (destructure-let
  508. expression
  509. (lambda (names values body)
  510. (->graph body
  511. (grow-environment
  512. environment
  513. names
  514. (%map-2 (lambda (name value)
  515. (let ((node (->graph value environment olam)))
  516. ;; Note that this may be clobbering a previous name,
  517. ;; since the node may come from another let, etc.
  518. ;; The outermost let wins!
  519. (if (not (eq? (node/type1 node) 'INPUT))
  520. (set-node/name! node name))
  521. node))
  522. names values))
  523. olam))))
  524. (define (lambda-body->graph lam env names nodes body)
  525. (let* ((body (->graph body
  526. (grow-environment env names nodes)
  527. lam))
  528. (node (node/make 'REDUCIBLE 'LAMBDA lam (list body))))
  529. (set-node/parents! body (cons node (node/parents node)))
  530. (set-lam/params! lam nodes)
  531. (set-lam/body! lam body)
  532. (set-lam/node! lam node)
  533. node))
  534. (define (lambda->graph expression environment olam)
  535. (destructure-lambda
  536. expression
  537. (lambda (names body)
  538. (let* ((lam (lam/make olam))
  539. (nodes
  540. (%map-1
  541. (lambda (name)
  542. ;; If *alpha-rename-lazily?* is false, this
  543. ;; alpha-renames eagerly.
  544. ;; Important kludge: Free variables not yet seen can't
  545. ;; present a conflict, thus it is fine to examine the
  546. ;; current snapshot of the global environment.
  547. (let ((new-name
  548. (if (and (not *alpha-rename-lazily?*)
  549. (or (j-lookup environment name)
  550. (table+/association *global-env* name)))
  551. (generate-new-name)
  552. name)))
  553. (node/make 'INPUT 'VARIABLE (var/make new-name lam))))
  554. names)))
  555. (lambda-body->graph lam environment names nodes body)))))
  556. ;;;; Input processor: utilities (continued)
  557. (define (combination->graph elements environment olam)
  558. (let ((operator (->graph (car elements) environment olam))
  559. (operands (%map-1 (lambda (child)
  560. (->graph child environment olam))
  561. (cdr elements))))
  562. ;; *** Handle this case specially ***
  563. ;; (eq? (node/type operator) 'LAMBDA)
  564. ;; For the time being it does nothing.
  565. (let* ((children (cons operator operands))
  566. (new-node (node/make 'REDUCIBLE 'COMBINATION false children)))
  567. (for-each (lambda (child)
  568. (set-node/parents!
  569. child
  570. (cons new-node (node/parents child))))
  571. children)
  572. (set-node/extra! new-node false)
  573. new-node)))
  574. ;;; Environment utilities
  575. (define-integrable (j-lookup environment var)
  576. (let ((place (assq var environment)))
  577. (and place
  578. (cdr place))))
  579. (define-integrable (grow-environment environment names values)
  580. (map* environment
  581. (lambda (name value)
  582. (cons name value))
  583. names
  584. values))
  585. ;;; operators
  586. (define-integrable (j-operator? node)
  587. (assq node *operators*))
  588. (define-integrable (can-reorder? node)
  589. (let ((place (assq node *operators*)))
  590. (and place
  591. (eq? 'ABELIAN-GROUP (cadr (cdr place))))))
  592. (define (process-operators operators)
  593. (let ((associations
  594. (%map-1 (lambda (var)
  595. (cons (var-node/name var)
  596. var))
  597. *global-vars*)))
  598. (delq false
  599. (%map-1 (lambda (operator)
  600. (let ((place (assq (car operator) associations)))
  601. (if place
  602. (cons (cdr place) operator)
  603. false)))
  604. operators))))
  605. ;;;; Input processor: syntactic utilities (continued)
  606. (define-integrable variable? symbol?)
  607. (define-integrable constant? number?)
  608. (define-integrable (generate-new-name)
  609. (new-uninterned-symbol "V-"))
  610. (define-integrable (generate-rename old)
  611. (new-uninterned-symbol
  612. (string-append (symbol->string old)
  613. "-")))
  614. (define (lambda-combination? expression)
  615. (and (pair? (car expression))
  616. (eq? (caar expression) 'LAMBDA)))
  617. (define (canonicalize-lambda-combination expression)
  618. (destructure-lambda
  619. (car expression)
  620. (lambda (params body)
  621. (let ((arguments (cdr expression)))
  622. (if (not (= (length arguments) (length params)))
  623. (error "canonicalize-lambda-combination: Wrong number of arguments"
  624. expression)
  625. `(LET (,@(%map-2 list params arguments))
  626. ,body))))))
  627. (define (canonicalize-let* expression)
  628. (let ((body (cddr expression))
  629. (bindings (cadr expression)))
  630. (define (process next rest)
  631. `(LET (,next)
  632. ,@(if (null? rest)
  633. body
  634. `(,(process (car rest) (cdr rest))))))
  635. (if (not (null? bindings))
  636. (process (car bindings) (cdr bindings))
  637. (prepare-body body expression "canonicalize-let*"))))
  638. (define (destructure-lambda expression recvr)
  639. (recvr (cadr expression)
  640. (prepare-body (cddr expression) expression "destructure-lambda")))
  641. (define (destructure-let expression recvr)
  642. (let ((bindings (cadr expression)))
  643. (recvr (%map-1 car bindings)
  644. (%map-1 cadr bindings)
  645. (prepare-body (cddr expression) expression "destructure-let"))))
  646. (define (prepare-body body expression name)
  647. (if (and (not (null? body))
  648. (null? (cdr body)))
  649. (car body)
  650. (begin
  651. (if *warn-body?*
  652. (warn (string-append name ": Body is a sequence") expression))
  653. `(BEGIN ,@body))))
  654. ;;;; Output processor: pass one, insert LETs to bind subexpressions.
  655. (define (sort-subexpressions! graph)
  656. (walk-graph!
  657. graph
  658. (lambda (node)
  659. (if (and (subexpression? node)
  660. (not (eq? (node/type1 node) 'INPUT)))
  661. (begin
  662. ;; (bkpt "sort-subexpressions!")
  663. (add-aux! node (find-target-lam node)))))))
  664. ;; A node is a subexpression if more than one node points at it.
  665. (define-integrable (subexpression? node)
  666. (let ((parents (node/parents node)))
  667. (and (pair? parents)
  668. (pair? (cdr parents)))))
  669. ;; This prevents migration past the binding point of variables, and
  670. ;; causes the proper nesting of lets in the output.
  671. (define (find-target-lam node)
  672. (map&reduce var-node/lam
  673. choose-descendant
  674. *global-lam*
  675. (node/input-set node)))
  676. ;; This does not remove the old node elements.
  677. ;; If we kept a "reference" count, we could do it,
  678. ;; but it does not hurt, since we are converting a copy
  679. ;; of the expression to an s-expression.
  680. ;; The only way it hurts is that we may get unnecessary
  681. ;; renamings since the conflict may have disappeared when
  682. ;; the subexpression was bound above the binding point
  683. ;; for the conflict.
  684. (define (propagate-input! var)
  685. (let ((target (lam/node (var-node/lam var))))
  686. (define (propagate! node)
  687. (if (and (not (eq? node target))
  688. (not (memq var (node/input-set node))))
  689. (begin
  690. (set-node/input-set!
  691. node
  692. (cons var (node/input-set node)))
  693. (for-each propagate! (node/parents node)))))
  694. (for-each propagate! (node/parents var))))
  695. ;;;; Output processor: pass one, LET-bind one subexpression
  696. (define (add-aux! node lam)
  697. (with-aux
  698. lam
  699. (lambda (lam aux)
  700. (let ((name (or (and *alpha-rename-lazily?*
  701. (node/name node))
  702. (generate-new-name))))
  703. (let ((var (node/make 'INPUT 'VARIABLE (var/make name aux)))
  704. (combination (lam/body lam)))
  705. (for-each
  706. (lambda (parent)
  707. (update-children!
  708. parent
  709. (subst var node (node/children parent))))
  710. (node/parents node))
  711. (set-lam/params! aux (cons var (lam/params aux)))
  712. (set-node/children!
  713. combination
  714. (let ((old-children (node/children combination)))
  715. (cons* (car old-children)
  716. node
  717. (cdr old-children))))
  718. (set-node/parents! var (node/parents node))
  719. (set-node/parents! node (list combination))
  720. (set-node/input-set! var (list var))
  721. (propagate-input! var))))))
  722. ;;; Main dispatch for graph->expression
  723. (define (->expression node)
  724. (case (node/type node)
  725. ((VARIABLE)
  726. ;; This can't be shadowed because of the preemptive renaming done
  727. ;; in lambda->graph.
  728. ;; If lambda->graph renames too many things, the capture avoidance
  729. ;; can be done at the output by doing another pass before the final
  730. ;; translation. This pass can detect conflicts and alpha rename.
  731. (var-node/name node))
  732. ((CONSTANT)
  733. (constant-node/value node))
  734. ((LAMBDA)
  735. `(lambda ,(%map-1 var-node/name (lam-node/params node))
  736. ,(lambda-body->expression node)))
  737. ((COMBINATION)
  738. (%map-1 ->expression (node/children node)))
  739. (else
  740. (error "->expression: Unknown node type" node))))
  741. ;;;; Output processor: pass one (continued)
  742. (define (with-aux lam recvr)
  743. (if (lam/aux lam)
  744. (recvr lam (lam/aux lam))
  745. (let ((old-node (lam/node lam))
  746. (old-body (lam/body lam))
  747. (new-lam (lam/make (lam/parent lam))))
  748. (let* ((new-body (node/make 'REDUCIBLE 'COMBINATION false
  749. (list old-node)))
  750. (new-node (node/make 'REDUCIBLE 'LAMBDA new-lam
  751. (list new-body))))
  752. (set-lam/aux! new-lam lam)
  753. (set-lam/parent! lam new-lam)
  754. (set-lam/params! new-lam (lam/params lam))
  755. (set-lam/params! lam '())
  756. (set-lam/body! new-lam new-body)
  757. (set-lam/node! new-lam new-node)
  758. (for-each
  759. (lambda (parent)
  760. (update-children!
  761. parent
  762. (subst new-node old-node (node/children parent))))
  763. (node/parents old-node))
  764. (set-node/parents! new-node (node/parents old-node))
  765. (set-node/parents! old-node (list new-body))
  766. (set-node/parents! new-body (list new-node))
  767. (set-node/input-set! new-node (node/input-set old-node))
  768. (set-node/input-set! old-node (node/input-set old-body))
  769. (set-node/input-set! new-body (node/input-set old-body))
  770. (let ((to-modify
  771. ;; This cannot use global-lam? since we are
  772. ;; editing the structure, and the parent
  773. ;; is in fact changing.
  774. (if (eq? lam *global-lam*)
  775. (begin
  776. (set! *global-lam* new-lam)
  777. *global-vars*)
  778. (lam/params new-lam))))
  779. (for-each (lambda (var-node)
  780. (set-var-node/lam! var-node new-lam))
  781. to-modify))
  782. (if (and (lam/parent new-lam)
  783. (eq? lam (lam/aux (lam/parent new-lam))))
  784. (set-lam/aux! (lam/parent new-lam) new-lam))
  785. (recvr new-lam lam)))))
  786. ;;;; Output processor: pass two, create the output
  787. (define (graph->expression graph)
  788. (if (not (eq? (node/type graph) 'LAMBDA))
  789. (error "graph->expression: Not a lambda" graph))
  790. (lambda-body->expression graph))
  791. (define (lambda-body->expression node)
  792. (define (collect node recvr)
  793. (let* ((lam (node/extra node))
  794. (body (lam/body lam)))
  795. (if (not (lam/aux lam))
  796. (recvr (->expression body)
  797. '())
  798. (collect
  799. (lam/node (lam/aux lam))
  800. (lambda (expr bindings)
  801. (recvr expr
  802. (cons
  803. (%map-2 (lambda (node value)
  804. (list (var-node/name node)
  805. (->expression value)))
  806. (lam/params (lam/aux lam))
  807. (cdr (node/children body)))
  808. bindings)))))))
  809. (collect node
  810. (lambda (body bindings)
  811. (define (finish bindings body)
  812. (cond ((null? bindings)
  813. body)
  814. ((null? (cdr bindings))
  815. `(LET ,bindings ,body))
  816. (else
  817. `(LET* ,bindings ,body))))
  818. (define (collect-lets bindings collected)
  819. (cond ((null? bindings)
  820. (finish (reverse collected) body))
  821. ((null? (cdar bindings))
  822. (collect-lets (cdr bindings)
  823. (cons (caar bindings)
  824. collected)))
  825. (else
  826. (finish (reverse collected)
  827. `(LET ,(car bindings)
  828. ,(collect-lets (cdr bindings) '()))))))
  829. (collect-lets bindings '()))))
  830. ;;;; Common utilities
  831. ;;; Free variable collection
  832. (define (collect-input-set! graph)
  833. (walk-graph!
  834. graph
  835. (lambda (node)
  836. (set-node/input-set!
  837. node
  838. (case (node/type node)
  839. ((VARIABLE)
  840. (list node))
  841. ((LAMBDA)
  842. (let ((lam (node/extra node)))
  843. (list-transform-negative
  844. (node/input-set (lam/body lam))
  845. (lambda (var-node)
  846. (eq? (var-node/lam var-node) lam)))))
  847. (else
  848. (map&reduce node/input-set
  849. eq-set/union '()
  850. (node/children node))))))))
  851. (define (alpha-rename! graph)
  852. (walk-graph!
  853. graph
  854. (lambda (node)
  855. (if (eq? (node/type node) 'LAMBDA)
  856. (let* ((lam (node/extra node))
  857. (free-vars (node/input-set node)))
  858. (if (not (null? free-vars))
  859. (for-each
  860. (lambda (param)
  861. (let* ((var (node/extra param))
  862. (name (var/name var)))
  863. (if (there-exists? free-vars
  864. (lambda (free-var)
  865. (eq? name (var-node/name free-var))))
  866. (begin
  867. ;; (bkpt "alpha-rename!")
  868. (set-var/name! var (generate-rename name))))))
  869. (lam/params lam))))))))
  870. ;;;; Common subexpression manipulation
  871. (define (grow-subexpressions! graph)
  872. (define (try-all subexps next-pass)
  873. (cond ((not (null? subexps))
  874. (try-all (cdr subexps)
  875. (possibly-grow-subexpression! (car subexps)
  876. next-pass)))
  877. ((not (null? next-pass))
  878. (try-all next-pass '()))
  879. (else
  880. unspecific)))
  881. (try-all (graph-accumulate
  882. graph
  883. (lambda (node rest)
  884. (if (subexpression? node)
  885. (cons node rest)
  886. rest))
  887. '())
  888. '()))
  889. (define (possibly-grow-subexpression! node acc)
  890. (let ((all (node/parents node)))
  891. (if (null? all)
  892. acc
  893. (let loop ((next (car all))
  894. (left (cdr all))
  895. (acc acc))
  896. (if (null? left)
  897. acc
  898. (loop (car left)
  899. (cdr left)
  900. (if (or (null? (node/children next)) ; deleted node
  901. (operator&not-only-operand? node next))
  902. acc
  903. (try-pairwise next left acc))))))))
  904. (define-integrable (operator&not-only-operand? node parent)
  905. (and (eq? node (combination-operator parent))
  906. #|
  907. ;; The code below is an open coding of this, for speed.
  908. (there-exists? (combination-operands parent)
  909. (lambda (node*)
  910. (not (eq? node node*))))
  911. |#
  912. (let loop ((rands (combination-operands parent)))
  913. (and (not (null? rands))
  914. (or (not (eq? node (car rands)))
  915. (loop (cdr rands)))))))
  916. (define (same-operands? l1 l2)
  917. (if (null? l1)
  918. (null? l2)
  919. (and (not (null? l2))
  920. (eq? (car l1) (car l2))
  921. (same-operands? (cdr l1) (cdr l2)))))
  922. ;;;; Common subexpression detector
  923. ;;; *** Improvements: lambda expressions currently not considered. ***
  924. ;;; It can be done by using the isomorphism tester that appears elsewhere,
  925. ;;; triggered if the list of free variables (input set) is the same,
  926. ;;; and the number of parameters is the same.
  927. (define (try-pairwise one others acc)
  928. (let loop ((others others)
  929. (acc acc))
  930. (if (or (null? others) (null? (node/parents one)))
  931. acc
  932. (loop (cdr others)
  933. (let ((result (try-pair one (car others))))
  934. (if result
  935. (multi-set/union result acc)
  936. acc))))))
  937. (define (try-pair one two)
  938. ;; *** Is the control structure correct? ***
  939. ;; It seems that multiple nodes should be returned for the next pass!
  940. (if (eq? one two)
  941. ;; Repeated children
  942. (and (can-reorder? (combination-operator one))
  943. (extract-repetitions! one))
  944. (and (not (null? (node/parents two)))
  945. (eq? (node/type one) (node/type two))
  946. (if (and (eq? 'COMBINATION (node/type one))
  947. (eq? (combination-operator one)
  948. (combination-operator two))
  949. (can-reorder? (combination-operator one)))
  950. (let ((set1 (combination-operands one))
  951. (set2 (combination-operands two)))
  952. (let ((common (multi-set/intersection set1 set2)))
  953. (cond ((null? common)
  954. (and (null? set1) (null? set2)
  955. (replace! two one)))
  956. ((null? (cdr common))
  957. (and (null? (cdr set1)) (null? (cdr set2))
  958. (replace! two one)))
  959. (else
  960. (let ((rem1 (multi-set/difference set1 common))
  961. (rem2 (multi-set/difference set2 common)))
  962. (cond ((null? rem1)
  963. (if (null? rem2)
  964. (replace! two one)
  965. (make-child! one two)))
  966. ((null? rem2)
  967. (make-child! two one))
  968. (else
  969. (let ((node
  970. (node/make
  971. 'REDUCIBLE
  972. 'COMBINATION
  973. false
  974. (cons (combination-operator one)
  975. common))))
  976. (set-node/input-set!
  977. node
  978. (map&reduce node/input-set
  979. eq-set/union
  980. '()
  981. common))
  982. (make-child! node one)
  983. (make-child! node two)))))))))
  984. (and (same-operands? (node/children one)
  985. (node/children two))
  986. (or (not (eq? (node/type one) 'LAMBDA))
  987. (= (length (lam-node/params one))
  988. (length (lam-node/params two))))
  989. (replace! two one))))))
  990. ;;;; Common subexpression eliminator
  991. (define (extract-repetitions! node)
  992. (let loop ((operands (reverse (combination-operands node)))
  993. (reptd '())
  994. (left '()))
  995. (cond ((null? operands)
  996. (and reptd
  997. (not (null? (cdr reptd)))
  998. (let ((new-node (node/make 'REDUCIBLE
  999. 'COMBINATION
  1000. false
  1001. (cons (combination-operator node)
  1002. reptd))))
  1003. (for-each
  1004. (lambda (reptd)
  1005. (set-node/parents!
  1006. reptd
  1007. (cons new-node
  1008. (delq-once node
  1009. (delq-once node
  1010. (node/parents reptd))))))
  1011. reptd)
  1012. (set-node/parents! new-node (list node node))
  1013. (update-children!
  1014. node
  1015. `(,(combination-operator node)
  1016. ,new-node
  1017. ,new-node
  1018. ,@left))
  1019. reptd)))
  1020. ((memq (car operands) left)
  1021. (loop (cdr operands)
  1022. (cons (car operands) reptd)
  1023. (delq (car operands) left)))
  1024. (else
  1025. (loop (cdr operands)
  1026. reptd
  1027. (cons (car operands) left))))))
  1028. ;;;; Common subexpression eliminator (continued)
  1029. (define (make-child! child parent)
  1030. (for-each
  1031. (lambda (child^2)
  1032. (update-parents!
  1033. child^2
  1034. (cons child (delq-once parent (node/parents child^2)))))
  1035. (node/children child))
  1036. (update-children!
  1037. parent
  1038. (cons (combination-operator parent)
  1039. (cons child
  1040. (multi-set/difference (combination-operands parent)
  1041. (combination-operands child)))))
  1042. (update-parents! child (cons parent (node/parents child)))
  1043. (list child))
  1044. (define (replace! two one)
  1045. ;; Replace two with one
  1046. (for-each (lambda (parent)
  1047. (update-children!
  1048. parent
  1049. (subst one two (node/children parent))))
  1050. (node/parents two))
  1051. (for-each (lambda (child)
  1052. (update-parents!
  1053. child
  1054. (subst one two (node/parents child))))
  1055. (node/children two))
  1056. (update-parents! one
  1057. ;; This could be eq-set/union,
  1058. ;; but update-parents! takes care
  1059. ;; to check each parent only once.
  1060. ;; eq-set/union would still not
  1061. ;; guarantee uniqueness since a node
  1062. ;; can have a parent more than once.
  1063. (multi-set/union (node/parents two)
  1064. (node/parents one)))
  1065. ;; This makes it no longer be a subexpression so that
  1066. ;; the top-level subexpression loop will ignore it
  1067. ;; if already cached.
  1068. (set-node/parents! two '())
  1069. (set-node/children! two '())
  1070. (list one))
  1071. (define (update-parents! node possible-parents)
  1072. (set-node/parents! node '())
  1073. (for-each (lambda (parent)
  1074. (set-node/mark! parent false))
  1075. possible-parents)
  1076. ;; This is done this way because there are multiple
  1077. ;; links that need to be maintained.
  1078. (let loop ((to-test possible-parents))
  1079. (and (not (null? to-test))
  1080. (let ((this (car to-test)))
  1081. (if (node/mark this)
  1082. (loop (cdr to-test))
  1083. (begin
  1084. (set-node/mark! this true)
  1085. (for-each
  1086. (lambda (child)
  1087. (if (eq? child node)
  1088. (set-node/parents!
  1089. node
  1090. (cons this
  1091. (node/parents node)))))
  1092. (node/children this))
  1093. (loop (cdr to-test))))))))
  1094. (define (update-children! parent new-children)
  1095. (set-node/children! parent new-children)
  1096. (if (eq? (node/type parent) 'LAMBDA)
  1097. (begin
  1098. (if (or (null? new-children)
  1099. (not (null? (cdr new-children))))
  1100. (error "IMPLEMENTATION-ERROR: update-children!: Clobbering lambda"
  1101. parent new-children))
  1102. (set-lam-node/body! parent (car new-children)))))
  1103. ;;;; Structure copier
  1104. (define (%expression/copy expression)
  1105. (let ((constants*
  1106. (%map-1 (lambda (constant)
  1107. (cons (car constant)
  1108. (copy-node (cdr constant))))
  1109. (expression/constants expression)))
  1110. (vars* (%map-1 copy-node (expression/variables expression)))
  1111. (global-lam* (copy-lam (expression/graph expression))))
  1112. (for-each (lambda (var*)
  1113. (set-var-node/lam! var* global-lam*))
  1114. vars*)
  1115. (expression/make (expression/lazy-rename? expression)
  1116. constants* vars* global-lam*)))
  1117. (define-integrable (object-copier %copy copy-fields!)
  1118. (lambda (object)
  1119. (or (table+/association *associations* object)
  1120. (let ((new-object (%copy object)))
  1121. (table+/associate! *associations* object new-object)
  1122. (copy-fields! new-object)
  1123. new-object))))
  1124. (define (%copy-lam-1 lam)
  1125. (let ((lam* (lam/make (lam/parent lam))))
  1126. (set-lam/params! lam* (lam/params lam))
  1127. (set-lam/body! lam* (lam/body lam))
  1128. (set-lam/node! lam* (lam/node lam))
  1129. (set-lam/aux! lam* (lam/aux lam))
  1130. lam*))
  1131. (define (%copy-lam-2 lam)
  1132. (if (lam/parent lam)
  1133. (set-lam/parent! lam (copy-lam (lam/parent lam))))
  1134. (if (lam/aux lam)
  1135. (set-lam/aux! lam (copy-lam (lam/aux lam))))
  1136. (set-lam/body! lam (copy-node (lam/body lam)))
  1137. (set-lam/node! lam (copy-node (lam/node lam)))
  1138. (set-lam/params! lam
  1139. (%map-1 (lambda (node)
  1140. (let ((node* (copy-node node)))
  1141. (set-var-node/lam! node* lam) ; fix-var
  1142. node*))
  1143. (lam/params lam))))
  1144. (define copy-lam
  1145. (object-copier %copy-lam-1 %copy-lam-2))
  1146. (define copy-var
  1147. ;; The lam field is set by the binding lam, in the line marked fix-var above.
  1148. (object-copier
  1149. (lambda (var)
  1150. (var/make (var/name var) false))
  1151. (lambda (new-var)
  1152. new-var)))
  1153. ;;;; Structure copier (continued)
  1154. (define (%copy-node-1 node)
  1155. (let ((new-node (node/make (node/type1 node)
  1156. (node/type2 node)
  1157. (node/extra node)
  1158. (node/children node))))
  1159. ;; parents set below when relinked by container.
  1160. (set-node/input-set! new-node (node/input-set node))
  1161. (set-node/name! new-node (node/name node))
  1162. new-node))
  1163. (define (%copy-node-2 node)
  1164. (set-node/input-set! node (%map-1 copy-node (node/input-set node)))
  1165. (set-node/children!
  1166. node
  1167. (%map-1 (lambda (node*)
  1168. (let ((node** (copy-node node*)))
  1169. (set-node/parents! node**
  1170. (cons node (node/parents node**)))
  1171. node**))
  1172. (node/children node)))
  1173. (set-node/extra!
  1174. node
  1175. (let ((current (node/extra node)))
  1176. (case (node/type node)
  1177. ((VARIABLE)
  1178. (copy-var current))
  1179. ((LAMBDA)
  1180. (copy-lam current))
  1181. ((CONSTANT COMBINATION)
  1182. current)
  1183. (else
  1184. (error "copy-node: Unknown type" node))))))
  1185. (define copy-node
  1186. (object-copier %copy-node-1 %copy-node-2))
  1187. ;;;; Binding
  1188. (define (%unify-1 expressions)
  1189. (let ((global-lam* (lam/make false))
  1190. (constants*
  1191. (initialize-constants! (%map-1 expression/constants expressions)))
  1192. (vars*
  1193. (initialize-variables! (%map-1 expression/variables expressions))))
  1194. (for-each (lambda (expr)
  1195. (copy-unify! (expression/graph expr) global-lam*))
  1196. expressions)
  1197. (expression/make true constants* vars* global-lam*)))
  1198. (define (%unify-2 expr* body)
  1199. (let* ((global-lam* (expression/graph expr*))
  1200. (node* (node/make 'REDUCIBLE 'LAMBDA global-lam*)))
  1201. (set-lam/node! global-lam* node*)
  1202. (for-each (lambda (const)
  1203. (%copy-node-2 (cdr const)))
  1204. (expression/constants expr*))
  1205. (for-each (lambda (var)
  1206. (%copy-node-2 var)
  1207. (set-var-node/lam! var global-lam*))
  1208. (expression/variables expr*))
  1209. (let ((body* (copy-node body)))
  1210. (set-lam/body! global-lam* body*)
  1211. (set-node/children! node* (list body*))
  1212. (set-node/parents! body* (cons node* (node/parents body*))))))
  1213. ;; *** Worry about binding operators ***
  1214. ;; binding to lambdas should become subexpressions where procedure, etc.
  1215. (define (%expression/bind expression bindings)
  1216. (split-list
  1217. (expression/variables expression)
  1218. (let ((to-be-bound (%map-1 car bindings)))
  1219. (lambda (var)
  1220. (memq (var-node/name var) to-be-bound)))
  1221. (lambda (bound unaffected)
  1222. (let* ((expr*
  1223. (%unify-1 (cons (expression/make true
  1224. (expression/constants expression)
  1225. unaffected
  1226. (expression/graph expression))
  1227. (%map-1 cadr bindings))))
  1228. (global-lam* (expression/graph expr*))
  1229. (bindings* (initialize-bindings! bindings global-lam*)))
  1230. ;; Bind!
  1231. (for-each
  1232. (lambda (bound)
  1233. (let* ((name (var-node/name bound))
  1234. (node (cdr (assq name bindings*))))
  1235. (set-node/name! node name)
  1236. (copy-unify! bound node)))
  1237. bound)
  1238. (%unify-2 expr* (lam/body (expression/graph expression)))
  1239. (for-each (lambda (binding)
  1240. (%copy-node-2 (cdr binding)))
  1241. bindings*)
  1242. expr*))))
  1243. ;;;; Binding (continued)
  1244. (define (initialize-constants! consts)
  1245. (reduce copy-unify-associations!
  1246. (%map-1 initialize-association! (car consts))
  1247. (cdr consts)))
  1248. (define (initialize-variables! vars)
  1249. (%map-1 cdr
  1250. (map&reduce (lambda (vars)
  1251. (%map-1 (lambda (var)
  1252. (cons (var-node/name var)
  1253. var))
  1254. vars))
  1255. copy-unify-associations!
  1256. (%map-1 (lambda (var)
  1257. (initialize-association!
  1258. (cons (var-node/name var)
  1259. var)))
  1260. (car vars))
  1261. (cdr vars))))
  1262. (define (initialize-bindings! bindings global-lam*)
  1263. (%map-1 (lambda (binding)
  1264. (let ((lam (expression/graph (cadr binding))))
  1265. (copy-unify! lam global-lam*)
  1266. (initialize-association!
  1267. (cons (car binding)
  1268. (lam/body lam)))))
  1269. bindings))
  1270. (define (copy-unify! object object*)
  1271. (let ((object** (table+/association *associations* object)))
  1272. (cond ((not object**)
  1273. (table+/associate! *associations* object object*))
  1274. ((not (eq? object* object**))
  1275. (error "copy-unify!: Already copy-unified"
  1276. object object* object**)))))
  1277. (define (initialize-association! asspair)
  1278. (cons (car asspair)
  1279. (let ((node (cdr asspair)))
  1280. (or (table+/association *associations* node)
  1281. (let ((node* (%copy-node-1 node)))
  1282. (table+/associate! *associations* node node*)
  1283. node*)))))
  1284. (define (copy-unify-associations! asspairs asspairs*)
  1285. (cond ((null? asspairs)
  1286. asspairs*)
  1287. ((assv (caar asspairs) asspairs*)
  1288. =>
  1289. (lambda (asspair*)
  1290. (copy-unify! (cdar asspairs) (cdr asspair*))
  1291. (copy-unify-associations! (cdr asspairs) asspairs*)))
  1292. (else
  1293. (copy-unify-associations!
  1294. (cdr asspairs)
  1295. (cons (initialize-association! (car asspairs))
  1296. asspairs*)))))
  1297. ;;;; Isomorphism tester
  1298. ;; This does not check the variables or constants lists.
  1299. ;; If they are equal, all of them will be met eventually.
  1300. ;; - Free variables should be OK as long as expression/bind fixes them.
  1301. ;; - Constants should be OK as long as they are removed if unneeded
  1302. ;; after constant folding. This can be done by checking the parents
  1303. ;; list. Currently there is no constant folding.
  1304. (define (%expression/equal? expression1 expression2)
  1305. (lam/equal? (expression/graph expression1)
  1306. (expression/graph expression2)))
  1307. (define-integrable (object-comparator %comparator)
  1308. (lambda (obj1 obj2)
  1309. (or (eq? obj1 obj2) ; when the objects share structure
  1310. (let ((assoc1 (table+/association *associations* obj1)))
  1311. (if assoc1
  1312. (eq? assoc1 obj2)
  1313. (and (not (table+/association *reverse-associations* obj2))
  1314. (begin
  1315. (table+/associate! *associations* obj1 obj2)
  1316. (table+/associate! *reverse-associations* obj2 obj1)
  1317. (%comparator obj1 obj2))))))))
  1318. (define node/equal?
  1319. (object-comparator
  1320. (lambda (node1 node2)
  1321. (and (eq? (node/type node1) (node/type node2))
  1322. (let ((extra1 (node/extra node1))
  1323. (extra2 (node/extra node2)))
  1324. (case (node/type node1)
  1325. ((VARIABLE)
  1326. (var/equal? extra1 extra2))
  1327. ((CONSTANT)
  1328. (eqv? extra1 extra2))
  1329. ((LAMBDA)
  1330. (lam/equal? extra1 extra2))
  1331. ((COMBINATION)
  1332. true)
  1333. (else
  1334. (error "node/equal?: Unknown type" node1))))
  1335. #|
  1336. ;; These two are not needed since if the rest of the structure
  1337. ;; is the same, these should be the same as well, unless the
  1338. ;; program is broken, and that does not happen (-: :-).
  1339. ;; The parents are impossible to do, since there is no a-priori
  1340. ;; way to match them, and the ordering need not be the same.
  1341. (node-set/equal? (node/parents node1)
  1342. (node/parents node2))
  1343. (node-set/equal? (node/input-set node1)
  1344. (node/input-set node2))
  1345. |#
  1346. (node-list/equal? (node/children node1)
  1347. (node/children node2))))))
  1348. ;;;; Isomorphism tester (continued)
  1349. (define (node-list/equal? list1 list2)
  1350. (let loop ((list1 list1)
  1351. (list2 list2))
  1352. (if (null? list1)
  1353. (null? list2)
  1354. (and (not (null? list2))
  1355. (node/equal? (car list1) (car list2))
  1356. (loop (cdr list1) (cdr list2))))))
  1357. (define lam/equal?
  1358. (object-comparator
  1359. (lambda (lam1 lam2)
  1360. (and (lam?/equal? (lam/parent lam1) (lam/parent lam2))
  1361. (lam?/equal? (lam/aux lam1) (lam/aux lam2))
  1362. (node/equal? (lam/node lam1) (lam/node lam2))
  1363. (node-list/equal? (lam/params lam1) (lam/params lam2))
  1364. (node/equal? (lam/body lam1) (lam/body lam2))))))
  1365. (define (lam?/equal? lam1 lam2)
  1366. (if (and lam1 lam2)
  1367. (lam/equal? lam1 lam2)
  1368. (and (not lam1) (not lam2))))
  1369. (define var/equal?
  1370. (object-comparator
  1371. (lambda (var1 var2)
  1372. ;; The names of globals must match. The names of others
  1373. ;; do not. The only thing that matters is position and nesting.
  1374. ;; Since position and nesting is taken care of by lam/equal?,
  1375. ;; we only need to compare the lams here.
  1376. ;; It is sufficient to check that lam1 is a global-lam, since
  1377. ;; lam/equal? guarantees that they occupy the same place in the
  1378. ;; environment tree.
  1379. (let ((lam1 (var/lam var1))
  1380. (lam2 (var/lam var2)))
  1381. (and (lam/equal? lam1 lam2)
  1382. (or (not (global-lam? lam1))
  1383. (eq? (var/name var1) (var/name var2))))))))
  1384. ;;;; Utilities for expression/process
  1385. (define-integrable (constant-value node)
  1386. (constant-node/value node))
  1387. (define-integrable (variable-name node)
  1388. (var-node/name node))
  1389. (define-integrable (lambda-parameters node)
  1390. (lam-node/params node))
  1391. (define-integrable (lambda-body node)
  1392. (lam-node/body node))
  1393. (define-integrable (combination-operator node)
  1394. (car (node/children node)))
  1395. (define-integrable (combination-operands node)
  1396. (cdr (node/children node)))
  1397. ;;;; Utilities for expression/process (continued)
  1398. (define (build-expression node)
  1399. (let ((expr
  1400. (expression/copy
  1401. (expression/make true
  1402. '()
  1403. '()
  1404. (node/extra (build-lambda '() node))))))
  1405. (relink-lambdas! expr)
  1406. (collect-input-set! (expression/node expr))
  1407. (let ((free-vars (node/input-set (expression/body expr)))
  1408. (lam (expression/graph expr)))
  1409. (for-each (lambda (var)
  1410. (set-var-node/lam! var lam))
  1411. free-vars)
  1412. (expression/make true
  1413. (collect-constants expr)
  1414. free-vars
  1415. (expression/graph expr)))))
  1416. (define (find-variable context node)
  1417. (if (global-lam? (var-node/lam node))
  1418. (intern-free-variable context (var-node/name node))
  1419. (or (table+/association (context/bound-vars context) node)
  1420. (error "find-variable: Not found!" node context))))
  1421. (define (build-lambda variables body)
  1422. ;; The parent field for the lambda will be set when the
  1423. ;; expression is relinked. Similarly for the parent field
  1424. ;; for body.
  1425. (let* ((lam (lam/make false))
  1426. (node (node/make 'REDUCIBLE 'LAMBDA lam (list body))))
  1427. (set-lam/params! lam variables)
  1428. (set-lam/body! lam body)
  1429. (set-lam/node! lam node)
  1430. (for-each (lambda (var)
  1431. (if (var-node/lam var)
  1432. (error "build-lambda: Rebinding variable" var)
  1433. (set-var-node/lam! var lam)))
  1434. variables)
  1435. node))
  1436. (define (bind-variables context variables)
  1437. (%map-1 (lambda (var)
  1438. (let ((table (context/bound-vars context)))
  1439. (if (table+/association table var)
  1440. (error "bind-variables: Already bound" var)
  1441. (let ((var* (build-variable (variable-name var))))
  1442. (table+/associate! table var var*)
  1443. var*))))
  1444. variables))
  1445. (define (build-combination operator operands)
  1446. ;; Parent field for children will be set when the
  1447. ;; expression is relinked.
  1448. (node/make 'REDUCIBLE 'COMBINATION
  1449. false
  1450. (cons operator operands)))
  1451. (define-integrable (make-interner selector maker)
  1452. (lambda (context value)
  1453. (or (table+/association (selector context) value)
  1454. (let ((node (maker value)))
  1455. (table+/associate! (selector context) value node)
  1456. node))))
  1457. ;;;; Utilities for expression/process (continued)
  1458. (define intern-constant
  1459. (make-interner context/constants
  1460. (lambda (constant)
  1461. (node/make 'INPUT 'CONSTANT constant))))
  1462. (define-integrable (build-variable name)
  1463. (node/make 'INPUT 'VARIABLE (var/make name false)))
  1464. (define intern-free-variable
  1465. (make-interner context/free-vars build-variable))
  1466. ;; letrec will make this fail!
  1467. (define (relink-lambdas! expr)
  1468. (define (walk-node node lam)
  1469. (cond ((not (eq? (node/type node) 'LAMBDA))
  1470. (for-each (lambda (child) (walk-node child lam))
  1471. (node/children node)))
  1472. ((lam/parent (node/extra node))
  1473. =>
  1474. (lambda (current-parent)
  1475. (let ((lam* (node/extra node)))
  1476. (if (not (eq? current-parent lam))
  1477. (let ((real-parent
  1478. (find-common-ancestor lam current-parent)))
  1479. (set-lam/parent! lam* real-parent)
  1480. (walk-node (lam/body lam*) lam*))))))
  1481. (else
  1482. (let ((lam* (node/extra node)))
  1483. (set-lam/parent! lam* lam)
  1484. (walk-node (lam/body lam*) lam)))))
  1485. (walk-node (expression/body expr)
  1486. (expression/graph expr)))
  1487. (define (find-common-ancestor lam1 lam2)
  1488. (define (collect-chain lam)
  1489. (cons lam
  1490. (let ((parent (lam/parent lam)))
  1491. (if parent
  1492. (collect-chain parent)
  1493. '()))))
  1494. (let ((chain1 (reverse (collect-chain lam1)))
  1495. (chain2 (reverse (collect-chain lam2))))
  1496. (if (not (eq? (car chain1) (car chain2)))
  1497. (error "find-common-ancestor: No common ancestor" lam1 lam2)
  1498. (let loop ((answer (car chain1))
  1499. (chain1 (cdr chain1))
  1500. (chain2 (cdr chain2)))
  1501. (if (or (null? chain1)
  1502. (null? chain2)
  1503. (not (eq? (car chain1) (car chain2))))
  1504. answer
  1505. (loop (car chain1) (cdr chain1) (cdr chain2)))))))
  1506. (define (collect-constants expr)
  1507. (graph-accumulate
  1508. (expression/node expr)
  1509. (lambda (node rest)
  1510. (if (eq? (node/type node) 'CONSTANT)
  1511. (cons (cons (constant-node/value node) node)
  1512. rest)
  1513. rest))
  1514. '()))
  1515. ;;;; Graph utilities
  1516. (define (walk-graph! graph procedure)
  1517. (if (not (null? (node/parents graph)))
  1518. (error "walk-graph!: Invoked on non-root" graph))
  1519. (let ((new-generation (1+ (node/generation graph))))
  1520. (define (walk-node node)
  1521. (if (not (= (node/generation node) new-generation))
  1522. (begin
  1523. (set-node/generation! node new-generation)
  1524. (for-each walk-node (node/children node))
  1525. (procedure node))))
  1526. (walk-node graph)))
  1527. (define (graph-accumulate graph accumulator null-value)
  1528. (if (not (null? (node/parents graph)))
  1529. (error "graph-accumulate: Invoked on non-root" graph))
  1530. (let ((new-generation (1+ (node/generation graph))))
  1531. (define (walk-node node result)
  1532. (if (= (node/generation node) new-generation)
  1533. result
  1534. (begin
  1535. (set-node/generation! node new-generation)
  1536. (accumulator node
  1537. ;; This does not use reduce because the current
  1538. ;; version ignores the initial value when the
  1539. ;; list is not empty.
  1540. (map&reduce identity-procedure walk-node result
  1541. (node/children node))))))
  1542. (walk-node graph null-value)))
  1543. (define (choose-descendant lam1 lam2)
  1544. (define (try start ancestor)
  1545. (let ((end *global-lam*))
  1546. (let loop ((next start))
  1547. (if (eq? next ancestor)
  1548. start
  1549. (and (not (eq? next end))
  1550. (loop (lam/parent next)))))))
  1551. (or (try lam1 lam2)
  1552. (try lam2 lam1)
  1553. (error "IMPLEMENTATION-ERROR: choose-descendant: cousins"
  1554. lam1 lam2)))
  1555. 'i-am-ready