Compiler-IR.st 20 KB

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