1
0

Compiler-IR.st 18 KB

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