Compiler-IR.st 18 KB

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