2
0

Compiler-IR.st 22 KB

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