Compiler-IR.st 26 KB

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