Compiler-IR.st 22 KB

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