1
0

Compiler-IR.st 20 KB

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