Compiler-IR.st 20 KB

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