Compiler-IR.st 21 KB

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