Compiler-IR.st 26 KB

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