1
0

Compiler-IR.st 22 KB

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