Compiler-IR.st 18 KB

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