Compiler-IR.st 21 KB

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