Compiler-IR.st 19 KB

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