1
0

Compiler-IR.st 22 KB

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