Compiler-IR.st 20 KB

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