Compiler-IR.st 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. Smalltalk current createPackage: 'Compiler-IR' properties: #{}!
  2. NodeVisitor subclass: #IRASTTranslator
  3. instanceVariableNames: 'source theClass method sequence nextAlias'
  4. package: 'Compiler-IR'!
  5. !IRASTTranslator commentStamp!
  6. I am the AST (abstract syntax tree) visitor responsible for building the intermediate representation graph.
  7. I rely on a builder object, instance of IRBuilder.!
  8. !IRASTTranslator methodsFor: 'accessing'!
  9. method
  10. ^ method
  11. !
  12. method: anIRMethod
  13. method := anIRMethod
  14. !
  15. nextAlias
  16. nextAlias ifNil: [ nextAlias := 0 ].
  17. nextAlias := nextAlias + 1.
  18. ^ nextAlias asString
  19. !
  20. sequence
  21. ^ sequence
  22. !
  23. sequence: anIRSequence
  24. sequence := anIRSequence
  25. !
  26. source
  27. ^ source
  28. !
  29. source: aString
  30. source := aString
  31. !
  32. theClass
  33. ^ theClass
  34. !
  35. theClass: aClass
  36. theClass := aClass
  37. !
  38. withSequence: aSequence do: aBlock
  39. | outerSequence |
  40. outerSequence := self sequence.
  41. self sequence: aSequence.
  42. aBlock value.
  43. self sequence: outerSequence.
  44. ^ aSequence
  45. ! !
  46. !IRASTTranslator methodsFor: 'visiting'!
  47. alias: aNode
  48. | variable |
  49. aNode isImmutable ifTrue: [ ^ self visit: aNode ].
  50. variable := IRVariable new
  51. variable: (AliasVar new name: '$', self nextAlias);
  52. yourself.
  53. self sequence add: (IRAssignment new
  54. add: variable;
  55. add: (self visit: aNode);
  56. yourself).
  57. self method internalVariables add: variable.
  58. ^ variable
  59. !
  60. aliasTemporally: aCollection
  61. "https://github.com/NicolasPetton/amber/issues/296
  62. If a node is aliased, all preceding ones are aliased as well.
  63. The tree is iterated twice. First we get the aliasing dependency,
  64. then the aliasing itself is done"
  65. | threshold result |
  66. threshold := 0.
  67. aCollection withIndexDo: [ :each :i |
  68. each subtreeNeedsAliasing
  69. ifTrue: [ threshold := i ]].
  70. result := OrderedCollection new.
  71. aCollection withIndexDo: [ :each :i |
  72. result add: (i <= threshold
  73. ifTrue: [ self alias: each ]
  74. ifFalse: [ self visit: each ])].
  75. ^result
  76. !
  77. visitAssignmentNode: aNode
  78. | left right assignment |
  79. right := self visit: aNode right.
  80. left := self visit: aNode left.
  81. self sequence add: (IRAssignment new
  82. add: left;
  83. add: right;
  84. yourself).
  85. ^ left
  86. !
  87. visitBlockNode: aNode
  88. | closure |
  89. closure := IRClosure new
  90. arguments: aNode parameters;
  91. scope: aNode scope;
  92. yourself.
  93. aNode scope temps do: [ :each |
  94. closure add: (IRTempDeclaration new
  95. name: each name;
  96. scope: aNode scope;
  97. yourself) ].
  98. aNode nodes do: [ :each | closure add: (self visit: each) ].
  99. ^ closure
  100. !
  101. visitBlockSequenceNode: aNode
  102. ^ self
  103. withSequence: IRBlockSequence new
  104. do: [
  105. aNode nodes ifNotEmpty: [
  106. aNode nodes allButLast do: [ :each |
  107. self sequence add: (self visit: each) ].
  108. aNode nodes last isReturnNode
  109. ifFalse: [ self sequence add: (IRBlockReturn new add: (self visit: aNode nodes last); yourself) ]
  110. ifTrue: [ self sequence add: (self visit: aNode nodes last) ]]]
  111. !
  112. visitCascadeNode: aNode
  113. | alias |
  114. aNode receiver isImmutable ifFalse: [
  115. alias := self alias: aNode receiver.
  116. aNode nodes do: [ :each |
  117. each receiver: (VariableNode new binding: alias variable) ]].
  118. aNode nodes allButLast do: [ :each |
  119. self sequence add: (self visit: each) ].
  120. ^ self alias: aNode nodes last
  121. !
  122. visitDynamicArrayNode: aNode
  123. | array |
  124. array := IRDynamicArray new.
  125. (self aliasTemporally: aNode nodes) do: [:each | array add: each].
  126. ^ array
  127. !
  128. visitDynamicDictionaryNode: aNode
  129. | dictionary |
  130. dictionary := IRDynamicDictionary new.
  131. (self aliasTemporally: aNode nodes) do: [:each | dictionary add: each].
  132. ^ dictionary
  133. !
  134. visitJSStatementNode: aNode
  135. ^ IRVerbatim new
  136. source: aNode source;
  137. yourself
  138. !
  139. visitMethodNode: aNode
  140. self method: (IRMethod new
  141. source: self source;
  142. theClass: self theClass;
  143. arguments: aNode arguments;
  144. selector: aNode selector;
  145. messageSends: aNode messageSends;
  146. superSends: aNode superSends;
  147. classReferences: aNode classReferences;
  148. scope: aNode scope;
  149. yourself).
  150. aNode scope temps do: [ :each |
  151. self method add: (IRTempDeclaration new
  152. name: each name;
  153. scope: aNode scope;
  154. yourself) ].
  155. aNode nodes do: [ :each | self method add: (self visit: each) ].
  156. aNode scope hasLocalReturn ifFalse: [
  157. (self method add: IRReturn new) add: (IRVariable new
  158. variable: (aNode scope pseudoVars at: 'self');
  159. yourself) ].
  160. ^ self method
  161. !
  162. visitReturnNode: aNode
  163. | return |
  164. return := aNode nonLocalReturn
  165. ifTrue: [ IRNonLocalReturn new ]
  166. ifFalse: [ IRReturn new ].
  167. return scope: aNode scope.
  168. aNode nodes do: [ :each |
  169. return add: (self alias: each) ].
  170. ^ return
  171. !
  172. visitSendNode: aNode
  173. | send all receiver arguments |
  174. send := IRSend new.
  175. send
  176. selector: aNode selector;
  177. index: aNode index.
  178. aNode superSend ifTrue: [ send classSend: self theClass superclass ].
  179. all := self aliasTemporally: { aNode receiver }, aNode arguments.
  180. receiver := all first.
  181. arguments := all allButFirst.
  182. send add: receiver.
  183. arguments do: [ :each | send add: each ].
  184. ^ send
  185. !
  186. visitSequenceNode: aNode
  187. ^ self
  188. withSequence: IRSequence new
  189. do: [
  190. aNode nodes do: [ :each | | instruction |
  191. instruction := self visit: each.
  192. instruction isVariable ifFalse: [
  193. self sequence add: instruction ]]]
  194. !
  195. visitValueNode: aNode
  196. ^ IRValue new
  197. value: aNode value;
  198. yourself
  199. !
  200. visitVariableNode: aNode
  201. ^ IRVariable new
  202. variable: aNode binding;
  203. yourself
  204. ! !
  205. Object subclass: #IRInstruction
  206. instanceVariableNames: 'parent instructions'
  207. package: 'Compiler-IR'!
  208. !IRInstruction commentStamp!
  209. I am the abstract root class of the IR (intermediate representation) instructions class hierarchy.
  210. The IR graph is used to emit JavaScript code using a JSStream.!
  211. !IRInstruction methodsFor: 'accessing'!
  212. instructions
  213. ^ instructions ifNil: [ instructions := OrderedCollection new ]
  214. !
  215. parent
  216. ^ parent
  217. !
  218. parent: anIRInstruction
  219. parent := anIRInstruction
  220. ! !
  221. !IRInstruction methodsFor: 'building'!
  222. add: anObject
  223. anObject parent: self.
  224. ^ self instructions add: anObject
  225. !
  226. remove
  227. self parent remove: self
  228. !
  229. remove: anIRInstruction
  230. self instructions remove: anIRInstruction
  231. !
  232. replace: anIRInstruction with: anotherIRInstruction
  233. anotherIRInstruction parent: self.
  234. self instructions
  235. at: (self instructions indexOf: anIRInstruction)
  236. put: anotherIRInstruction
  237. !
  238. replaceWith: anIRInstruction
  239. self parent replace: self with: anIRInstruction
  240. ! !
  241. !IRInstruction methodsFor: 'testing'!
  242. canBeAssigned
  243. ^ true
  244. !
  245. isClosure
  246. ^ false
  247. !
  248. isInlined
  249. ^ false
  250. !
  251. isLocalReturn
  252. ^ false
  253. !
  254. isReturn
  255. ^ false
  256. !
  257. isSend
  258. ^ false
  259. !
  260. isSequence
  261. ^ false
  262. !
  263. isTempDeclaration
  264. ^ false
  265. !
  266. isVariable
  267. ^ false
  268. ! !
  269. !IRInstruction methodsFor: 'visiting'!
  270. accept: aVisitor
  271. ^ aVisitor visitIRInstruction: self
  272. ! !
  273. !IRInstruction class methodsFor: 'instance creation'!
  274. on: aBuilder
  275. ^ self new
  276. builder: aBuilder;
  277. yourself
  278. ! !
  279. IRInstruction subclass: #IRAssignment
  280. instanceVariableNames: ''
  281. package: 'Compiler-IR'!
  282. !IRAssignment methodsFor: 'visiting'!
  283. accept: aVisitor
  284. ^ aVisitor visitIRAssignment: self
  285. ! !
  286. IRInstruction subclass: #IRDynamicArray
  287. instanceVariableNames: ''
  288. package: 'Compiler-IR'!
  289. !IRDynamicArray methodsFor: 'visiting'!
  290. accept: aVisitor
  291. ^ aVisitor visitIRDynamicArray: self
  292. ! !
  293. IRInstruction subclass: #IRDynamicDictionary
  294. instanceVariableNames: ''
  295. package: 'Compiler-IR'!
  296. !IRDynamicDictionary methodsFor: 'visiting'!
  297. accept: aVisitor
  298. ^ aVisitor visitIRDynamicDictionary: self
  299. ! !
  300. IRInstruction subclass: #IRScopedInstruction
  301. instanceVariableNames: 'scope'
  302. package: 'Compiler-IR'!
  303. !IRScopedInstruction methodsFor: 'accessing'!
  304. scope
  305. ^ scope
  306. !
  307. scope: aScope
  308. scope := aScope
  309. ! !
  310. IRScopedInstruction subclass: #IRClosure
  311. instanceVariableNames: 'arguments'
  312. package: 'Compiler-IR'!
  313. !IRClosure methodsFor: 'accessing'!
  314. arguments
  315. ^ arguments ifNil: [ #() ]
  316. !
  317. arguments: aCollection
  318. arguments := aCollection
  319. !
  320. scope: aScope
  321. super scope: aScope.
  322. aScope instruction: self
  323. !
  324. sequence
  325. ^ self instructions last
  326. !
  327. tempDeclarations
  328. ^ self instructions select: [ :each |
  329. each isTempDeclaration ]
  330. ! !
  331. !IRClosure methodsFor: 'testing'!
  332. isClosure
  333. ^ true
  334. ! !
  335. !IRClosure methodsFor: 'visiting'!
  336. accept: aVisitor
  337. ^ aVisitor visitIRClosure: self
  338. ! !
  339. IRScopedInstruction subclass: #IRMethod
  340. instanceVariableNames: 'theClass source selector classReferences messageSends superSends arguments internalVariables'
  341. package: 'Compiler-IR'!
  342. !IRMethod commentStamp!
  343. I am a method instruction!
  344. !IRMethod methodsFor: 'accessing'!
  345. arguments
  346. ^ arguments
  347. !
  348. arguments: aCollection
  349. arguments := aCollection
  350. !
  351. classReferences
  352. ^ classReferences
  353. !
  354. classReferences: aCollection
  355. classReferences := aCollection
  356. !
  357. internalVariables
  358. ^ internalVariables ifNil: [ internalVariables := Set new ]
  359. !
  360. messageSends
  361. ^ messageSends
  362. !
  363. messageSends: aCollection
  364. messageSends := aCollection
  365. !
  366. scope: aScope
  367. super scope: aScope.
  368. aScope instruction: self
  369. !
  370. selector
  371. ^ selector
  372. !
  373. selector: aString
  374. selector := aString
  375. !
  376. source
  377. ^ source
  378. !
  379. source: aString
  380. source := aString
  381. !
  382. superSends
  383. ^ superSends
  384. !
  385. superSends: aCollection
  386. superSends := aCollection
  387. !
  388. tempDeclarations
  389. ^ self instructions select: [ :each |
  390. each isTempDeclaration ]
  391. !
  392. theClass
  393. ^ theClass
  394. !
  395. theClass: aClass
  396. theClass := aClass
  397. ! !
  398. !IRMethod methodsFor: 'visiting'!
  399. accept: aVisitor
  400. ^ aVisitor visitIRMethod: self
  401. ! !
  402. IRScopedInstruction subclass: #IRReturn
  403. instanceVariableNames: ''
  404. package: 'Compiler-IR'!
  405. !IRReturn commentStamp!
  406. I am a local return instruction.!
  407. !IRReturn methodsFor: 'testing'!
  408. canBeAssigned
  409. ^ false
  410. !
  411. isBlockReturn
  412. ^ false
  413. !
  414. isLocalReturn
  415. ^ true
  416. !
  417. isNonLocalReturn
  418. ^ self isLocalReturn not
  419. !
  420. isReturn
  421. ^ true
  422. ! !
  423. !IRReturn methodsFor: 'visiting'!
  424. accept: aVisitor
  425. ^ aVisitor visitIRReturn: self
  426. ! !
  427. IRReturn subclass: #IRBlockReturn
  428. instanceVariableNames: ''
  429. package: 'Compiler-IR'!
  430. !IRBlockReturn commentStamp!
  431. Smalltalk blocks return their last statement. I am a implicit block return instruction.!
  432. !IRBlockReturn methodsFor: 'testing'!
  433. isBlockReturn
  434. ^ true
  435. ! !
  436. !IRBlockReturn methodsFor: 'visiting'!
  437. accept: aVisitor
  438. ^ aVisitor visitIRBlockReturn: self
  439. ! !
  440. IRReturn subclass: #IRNonLocalReturn
  441. instanceVariableNames: ''
  442. package: 'Compiler-IR'!
  443. !IRNonLocalReturn commentStamp!
  444. I am a non local return instruction.
  445. Non local returns are handled using a try/catch JS statement.
  446. See IRNonLocalReturnHandling class!
  447. !IRNonLocalReturn methodsFor: 'testing'!
  448. isLocalReturn
  449. ^ false
  450. ! !
  451. !IRNonLocalReturn methodsFor: 'visiting'!
  452. accept: aVisitor
  453. ^ aVisitor visitIRNonLocalReturn: self
  454. ! !
  455. IRScopedInstruction subclass: #IRTempDeclaration
  456. instanceVariableNames: 'name'
  457. package: 'Compiler-IR'!
  458. !IRTempDeclaration methodsFor: 'accessing'!
  459. name
  460. ^ name
  461. !
  462. name: aString
  463. name := aString
  464. ! !
  465. !IRTempDeclaration methodsFor: 'testing'!
  466. isTempDeclaration
  467. ^ true
  468. ! !
  469. !IRTempDeclaration methodsFor: 'visiting'!
  470. accept: aVisitor
  471. ^ aVisitor visitIRTempDeclaration: self
  472. ! !
  473. IRInstruction subclass: #IRSend
  474. instanceVariableNames: 'selector classSend index'
  475. package: 'Compiler-IR'!
  476. !IRSend commentStamp!
  477. I am a message send instruction.!
  478. !IRSend methodsFor: 'accessing'!
  479. classSend
  480. ^ classSend
  481. !
  482. classSend: aClass
  483. classSend := aClass
  484. !
  485. index
  486. ^ index
  487. !
  488. index: anInteger
  489. index := anInteger
  490. !
  491. javascriptSelector
  492. ^ self classSend
  493. ifNil: [ self selector asSelector ]
  494. ifNotNil: [ self selector asSuperSelector ]
  495. !
  496. selector
  497. ^ selector
  498. !
  499. selector: aString
  500. selector := aString
  501. ! !
  502. !IRSend methodsFor: 'testing'!
  503. isSend
  504. ^ true
  505. ! !
  506. !IRSend methodsFor: 'visiting'!
  507. accept: aVisitor
  508. ^ aVisitor visitIRSend: self
  509. ! !
  510. IRInstruction subclass: #IRSequence
  511. instanceVariableNames: ''
  512. package: 'Compiler-IR'!
  513. !IRSequence methodsFor: 'testing'!
  514. isSequence
  515. ^ true
  516. ! !
  517. !IRSequence methodsFor: 'visiting'!
  518. accept: aVisitor
  519. ^ aVisitor visitIRSequence: self
  520. ! !
  521. IRSequence subclass: #IRBlockSequence
  522. instanceVariableNames: ''
  523. package: 'Compiler-IR'!
  524. !IRBlockSequence methodsFor: 'visiting'!
  525. accept: aVisitor
  526. ^ aVisitor visitIRBlockSequence: self
  527. ! !
  528. IRInstruction subclass: #IRValue
  529. instanceVariableNames: 'value'
  530. package: 'Compiler-IR'!
  531. !IRValue commentStamp!
  532. I am the simplest possible instruction. I represent a value.!
  533. !IRValue methodsFor: 'accessing'!
  534. value
  535. ^value
  536. !
  537. value: aString
  538. value := aString
  539. ! !
  540. !IRValue methodsFor: 'visiting'!
  541. accept: aVisitor
  542. ^ aVisitor visitIRValue: self
  543. ! !
  544. IRInstruction subclass: #IRVariable
  545. instanceVariableNames: 'variable'
  546. package: 'Compiler-IR'!
  547. !IRVariable commentStamp!
  548. I am a variable instruction.!
  549. !IRVariable methodsFor: 'accessing'!
  550. variable
  551. ^ variable
  552. !
  553. variable: aScopeVariable
  554. variable := aScopeVariable
  555. ! !
  556. !IRVariable methodsFor: 'testing'!
  557. isVariable
  558. ^ true
  559. ! !
  560. !IRVariable methodsFor: 'visiting'!
  561. accept: aVisitor
  562. ^ aVisitor visitIRVariable: self
  563. ! !
  564. IRInstruction subclass: #IRVerbatim
  565. instanceVariableNames: 'source'
  566. package: 'Compiler-IR'!
  567. !IRVerbatim methodsFor: 'accessing'!
  568. source
  569. ^ source
  570. !
  571. source: aString
  572. source := aString
  573. ! !
  574. !IRVerbatim methodsFor: 'visiting'!
  575. accept: aVisitor
  576. ^ aVisitor visitIRVerbatim: self
  577. ! !
  578. Object subclass: #IRVisitor
  579. instanceVariableNames: ''
  580. package: 'Compiler-IR'!
  581. !IRVisitor methodsFor: 'visiting'!
  582. visit: anIRInstruction
  583. ^ anIRInstruction accept: self
  584. !
  585. visitIRAssignment: anIRAssignment
  586. ^ self visitIRInstruction: anIRAssignment
  587. !
  588. visitIRBlockReturn: anIRBlockReturn
  589. ^ self visitIRReturn: anIRBlockReturn
  590. !
  591. visitIRBlockSequence: anIRBlockSequence
  592. ^ self visitIRSequence: anIRBlockSequence
  593. !
  594. visitIRClosure: anIRClosure
  595. ^ self visitIRInstruction: anIRClosure
  596. !
  597. visitIRDynamicArray: anIRDynamicArray
  598. ^ self visitIRInstruction: anIRDynamicArray
  599. !
  600. visitIRDynamicDictionary: anIRDynamicDictionary
  601. ^ self visitIRInstruction: anIRDynamicDictionary
  602. !
  603. visitIRInlinedClosure: anIRInlinedClosure
  604. ^ self visitIRClosure: anIRInlinedClosure
  605. !
  606. visitIRInlinedSequence: anIRInlinedSequence
  607. ^ self visitIRSequence: anIRInlinedSequence
  608. !
  609. visitIRInstruction: anIRInstruction
  610. anIRInstruction instructions do: [ :each | self visit: each ].
  611. ^ anIRInstruction
  612. !
  613. visitIRMethod: anIRMethod
  614. ^ self visitIRInstruction: anIRMethod
  615. !
  616. visitIRNonLocalReturn: anIRNonLocalReturn
  617. ^ self visitIRInstruction: anIRNonLocalReturn
  618. !
  619. visitIRNonLocalReturnHandling: anIRNonLocalReturnHandling
  620. ^ self visitIRInstruction: anIRNonLocalReturnHandling
  621. !
  622. visitIRReturn: anIRReturn
  623. ^ self visitIRInstruction: anIRReturn
  624. !
  625. visitIRSend: anIRSend
  626. ^ self visitIRInstruction: anIRSend
  627. !
  628. visitIRSequence: anIRSequence
  629. ^ self visitIRInstruction: anIRSequence
  630. !
  631. visitIRTempDeclaration: anIRTempDeclaration
  632. ^ self visitIRInstruction: anIRTempDeclaration
  633. !
  634. visitIRValue: anIRValue
  635. ^ self visitIRInstruction: anIRValue
  636. !
  637. visitIRVariable: anIRVariable
  638. ^ self visitIRInstruction: anIRVariable
  639. !
  640. visitIRVerbatim: anIRVerbatim
  641. ^ self visitIRInstruction: anIRVerbatim
  642. ! !
  643. IRVisitor subclass: #IRJSTranslator
  644. instanceVariableNames: 'stream'
  645. package: 'Compiler-IR'!
  646. !IRJSTranslator methodsFor: 'accessing'!
  647. contents
  648. ^ self stream contents
  649. !
  650. stream
  651. ^ stream
  652. !
  653. stream: aStream
  654. stream := aStream
  655. ! !
  656. !IRJSTranslator methodsFor: 'initialization'!
  657. initialize
  658. super initialize.
  659. stream := JSStream new.
  660. ! !
  661. !IRJSTranslator methodsFor: 'visiting'!
  662. visitIRAssignment: anIRAssignment
  663. self visit: anIRAssignment instructions first.
  664. self stream nextPutAssignment.
  665. self visit: anIRAssignment instructions last.
  666. !
  667. visitIRClosure: anIRClosure
  668. self stream
  669. nextPutClosureWith: [
  670. self stream nextPutVars: (anIRClosure tempDeclarations collect: [ :each |
  671. each name asVariableName ]).
  672. self stream
  673. nextPutBlockContextFor: anIRClosure
  674. during: [ super visitIRClosure: anIRClosure ] ]
  675. arguments: anIRClosure arguments
  676. !
  677. visitIRDynamicArray: anIRDynamicArray
  678. self stream nextPutAll: '['.
  679. anIRDynamicArray instructions
  680. do: [ :each | self visit: each ]
  681. separatedBy: [ self stream nextPutAll: ',' ].
  682. stream nextPutAll: ']'
  683. !
  684. visitIRDynamicDictionary: anIRDynamicDictionary
  685. self stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
  686. anIRDynamicDictionary instructions
  687. do: [ :each | self visit: each ]
  688. separatedBy: [self stream nextPutAll: ',' ].
  689. self stream nextPutAll: '])'
  690. !
  691. visitIRMethod: anIRMethod
  692. self stream
  693. nextPutMethodDeclaration: anIRMethod
  694. with: [ self stream
  695. nextPutFunctionWith: [
  696. self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |
  697. each name asVariableName ]).
  698. self stream nextPutContextFor: anIRMethod during: [
  699. anIRMethod internalVariables notEmpty ifTrue: [
  700. self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |
  701. each variable alias ]) ].
  702. anIRMethod scope hasNonLocalReturn
  703. ifTrue: [
  704. self stream nextPutNonLocalReturnHandlingWith: [
  705. super visitIRMethod: anIRMethod ]]
  706. ifFalse: [ super visitIRMethod: anIRMethod ]]]
  707. arguments: anIRMethod arguments ]
  708. !
  709. visitIRNonLocalReturn: anIRNonLocalReturn
  710. self stream nextPutNonLocalReturnWith: [
  711. super visitIRNonLocalReturn: anIRNonLocalReturn ]
  712. !
  713. visitIRReturn: anIRReturn
  714. self stream nextPutReturnWith: [
  715. super visitIRReturn: anIRReturn ]
  716. !
  717. visitIRSend: anIRSend
  718. anIRSend classSend
  719. ifNil: [
  720. self stream nextPutAll: '_st('.
  721. self visit: anIRSend instructions first.
  722. self stream nextPutAll: ').', anIRSend selector asSelector, '('.
  723. anIRSend instructions allButFirst
  724. do: [ :each | self visit: each ]
  725. separatedBy: [ self stream nextPutAll: ',' ].
  726. self stream nextPutAll: ')' ]
  727. ifNotNil: [
  728. self stream
  729. nextPutAll: anIRSend classSend asJavascript, '.fn.prototype.';
  730. nextPutAll: anIRSend selector asSelector, '.apply(';
  731. nextPutAll: '_st('.
  732. self visit: anIRSend instructions first.
  733. self stream nextPutAll: '), ['.
  734. anIRSend instructions allButFirst
  735. do: [ :each | self visit: each ]
  736. separatedBy: [ self stream nextPutAll: ',' ].
  737. self stream nextPutAll: '])' ]
  738. !
  739. visitIRSequence: anIRSequence
  740. self stream nextPutSequenceWith: [
  741. anIRSequence instructions do: [ :each |
  742. self stream nextPutStatementWith: (self visit: each) ]]
  743. !
  744. visitIRTempDeclaration: anIRTempDeclaration
  745. "self stream
  746. nextPutAll: 'var ', anIRTempDeclaration name asVariableName, ';';
  747. lf"
  748. !
  749. visitIRValue: anIRValue
  750. self stream nextPutAll: anIRValue value asJavascript
  751. !
  752. visitIRVariable: anIRVariable
  753. anIRVariable variable name = 'thisContext'
  754. ifTrue: [ self stream nextPutAll: 'smalltalk.getThisContext()' ]
  755. ifFalse: [ self stream nextPutAll: anIRVariable variable alias ]
  756. !
  757. visitIRVerbatim: anIRVerbatim
  758. self stream nextPutStatementWith: [
  759. self stream nextPutAll: anIRVerbatim source ]
  760. ! !
  761. Object subclass: #JSStream
  762. instanceVariableNames: 'stream'
  763. package: 'Compiler-IR'!
  764. !JSStream methodsFor: 'accessing'!
  765. contents
  766. ^ stream contents
  767. ! !
  768. !JSStream methodsFor: 'initialization'!
  769. initialize
  770. super initialize.
  771. stream := '' writeStream.
  772. ! !
  773. !JSStream methodsFor: 'streaming'!
  774. lf
  775. stream lf
  776. !
  777. nextPut: aString
  778. stream nextPut: aString
  779. !
  780. nextPutAll: aString
  781. stream nextPutAll: aString
  782. !
  783. nextPutAssignment
  784. stream nextPutAll: '='
  785. !
  786. nextPutBlockContextFor: anIRClosure during: aBlock
  787. self
  788. nextPutAll: 'return smalltalk.withContext(function(', anIRClosure scope alias, ') {';
  789. nextPutAll: String cr.
  790. aBlock value.
  791. self
  792. nextPutAll: '}, function(', anIRClosure scope alias, ') {';
  793. nextPutAll: anIRClosure scope alias, '.fillBlock(['.
  794. anIRClosure arguments
  795. do: [ :each | self nextPutAll: each asVariableName ]
  796. separatedBy: [ self nextPutAll: ',' ].
  797. self nextPutAll: '], {'.
  798. anIRClosure tempDeclarations
  799. do: [ :each |
  800. self
  801. nextPutAll: each name asVariableName;
  802. nextPutAll: ':';
  803. nextPutAll: each name asVariableName]
  804. separatedBy: [ self nextPutAll: ',' ].
  805. self
  806. nextPutAll: '})})'
  807. !
  808. nextPutClosureWith: aBlock arguments: anArray
  809. stream nextPutAll: '(function('.
  810. anArray
  811. do: [ :each | stream nextPutAll: each asVariableName ]
  812. separatedBy: [ stream nextPut: ',' ].
  813. stream nextPutAll: '){'; lf.
  814. aBlock value.
  815. stream nextPutAll: '})'
  816. !
  817. nextPutContextFor: aMethod during: aBlock
  818. self
  819. nextPutAll: 'return smalltalk.withContext(function(', aMethod scope alias, ') { ';
  820. nextPutAll: String cr.
  821. aBlock value.
  822. self
  823. nextPutAll: '}, function(', aMethod scope alias, ') {', aMethod scope alias;
  824. nextPutAll: '.fill(self,', aMethod selector asJavascript, ', ['.
  825. aMethod arguments
  826. do: [ :each | self nextPutAll: each asVariableName ]
  827. separatedBy: [ self nextPutAll: ',' ].
  828. self nextPutAll: '], {'.
  829. aMethod tempDeclarations
  830. do: [ :each |
  831. self
  832. nextPutAll: each name asVariableName;
  833. nextPutAll: ':';
  834. nextPutAll: each name asVariableName]
  835. separatedBy: [ self nextPutAll: ',' ].
  836. self
  837. nextPutAll: '}, ';
  838. nextPutAll: aMethod theClass asJavascript;
  839. nextPutAll: ')})'
  840. !
  841. nextPutFunctionWith: aBlock arguments: anArray
  842. stream nextPutAll: 'fn: function('.
  843. anArray
  844. do: [ :each | stream nextPutAll: each asVariableName ]
  845. separatedBy: [ stream nextPut: ',' ].
  846. stream nextPutAll: '){'; lf.
  847. stream nextPutAll: 'var self=this;'; lf.
  848. aBlock value.
  849. stream nextPutAll: '}'
  850. !
  851. nextPutIf: aBlock with: anotherBlock
  852. stream nextPutAll: 'if('.
  853. aBlock value.
  854. stream nextPutAll: '){'; lf.
  855. anotherBlock value.
  856. stream nextPutAll: '}'
  857. !
  858. nextPutIfElse: aBlock with: ifBlock with: elseBlock
  859. stream nextPutAll: 'if('.
  860. aBlock value.
  861. stream nextPutAll: '){'; lf.
  862. ifBlock value.
  863. stream nextPutAll: '} else {'; lf.
  864. elseBlock value.
  865. stream nextPutAll: '}'
  866. !
  867. nextPutMethodDeclaration: aMethod with: aBlock
  868. stream
  869. nextPutAll: 'smalltalk.method({'; lf;
  870. nextPutAll: 'selector: "', aMethod selector, '",'; lf;
  871. nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.
  872. aBlock value.
  873. stream
  874. nextPutAll: ',', String lf, 'messageSends: ';
  875. nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
  876. nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
  877. nextPutAll: 'referencedClasses: ['.
  878. aMethod classReferences
  879. do: [:each | stream nextPutAll: each asJavascript]
  880. separatedBy: [stream nextPutAll: ','].
  881. stream
  882. nextPutAll: ']';
  883. nextPutAll: '})'
  884. !
  885. nextPutNonLocalReturnHandlingWith: aBlock
  886. stream
  887. nextPutAll: 'var $early={};'; lf;
  888. nextPutAll: 'try {'; lf.
  889. aBlock value.
  890. stream
  891. nextPutAll: '}'; lf;
  892. nextPutAll: 'catch(e) {if(e===$early)return e[0]; throw e}'; lf
  893. !
  894. nextPutNonLocalReturnWith: aBlock
  895. stream nextPutAll: 'throw $early=['.
  896. aBlock value.
  897. stream nextPutAll: ']'
  898. !
  899. nextPutReturn
  900. stream nextPutAll: 'return '
  901. !
  902. nextPutReturnWith: aBlock
  903. self nextPutReturn.
  904. aBlock value
  905. !
  906. nextPutSequenceWith: aBlock
  907. "stream
  908. nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."
  909. aBlock value.
  910. "stream
  911. nextPutAll: '};'; lf"
  912. !
  913. nextPutStatement: anInteger with: aBlock
  914. stream nextPutAll: 'case ', anInteger asString, ':'; lf.
  915. self nextPutStatementWith: aBlock.
  916. stream nextPutAll: 'smalltalk.thisContext.pc=', (anInteger + 1) asString, ';'; lf
  917. !
  918. nextPutStatementWith: aBlock
  919. aBlock value.
  920. stream nextPutAll: ';'; lf
  921. !
  922. nextPutVar: aString
  923. stream nextPutAll: 'var ', aString, ';'; lf
  924. !
  925. nextPutVars: aCollection
  926. aCollection ifEmpty: [ ^self ].
  927. stream nextPutAll: 'var '.
  928. aCollection
  929. do: [ :each | stream nextPutAll: each ]
  930. separatedBy: [ stream nextPutAll: ',' ].
  931. stream nextPutAll: ';'; lf
  932. ! !
  933. !BlockClosure methodsFor: '*Compiler-IR'!
  934. appendToInstruction: anIRInstruction
  935. anIRInstruction appendBlock: self
  936. ! !
  937. !String methodsFor: '*Compiler-IR'!
  938. asVariableName
  939. ^ (Smalltalk current reservedWords includes: self)
  940. ifTrue: [ self, '_' ]
  941. ifFalse: [ self ]
  942. ! !