1
0

Compiler-Visitors.st 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. Smalltalk current createPackage: 'Compiler-Visitors' properties: #{}!
  2. NodeVisitor subclass: #AbstractCodeGenerator
  3. instanceVariableNames: 'currentClass source'
  4. package: 'Compiler-Visitors'!
  5. !AbstractCodeGenerator methodsFor: 'accessing'!
  6. classNameFor: aClass
  7. ^aClass isMetaclass
  8. ifTrue: [aClass instanceClass name, '.klass']
  9. ifFalse: [
  10. aClass isNil
  11. ifTrue: ['nil']
  12. ifFalse: [aClass name]]
  13. !
  14. currentClass
  15. ^currentClass
  16. !
  17. currentClass: aClass
  18. currentClass := aClass
  19. !
  20. pseudoVariables
  21. ^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
  22. !
  23. safeVariableNameFor: aString
  24. ^(Smalltalk current reservedWords includes: aString)
  25. ifTrue: [aString, '_']
  26. ifFalse: [aString]
  27. !
  28. source
  29. ^source ifNil: ['']
  30. !
  31. source: aString
  32. source := aString
  33. ! !
  34. !AbstractCodeGenerator methodsFor: 'compiling'!
  35. compileNode: aNode
  36. self subclassResponsibility
  37. ! !
  38. AbstractCodeGenerator subclass: #CodeGenerator
  39. instanceVariableNames: ''
  40. package: 'Compiler-Visitors'!
  41. !CodeGenerator methodsFor: 'compiling'!
  42. compileNode: aNode
  43. | ir stream |
  44. self semanticAnalyzer visit: aNode.
  45. ir := self translator visit: aNode; builder.
  46. stream := JSStream new.
  47. ir emitOn: stream.
  48. ^ stream contents
  49. !
  50. semanticAnalyzer
  51. ^ SemanticAnalyzer on: self currentClass
  52. !
  53. translator
  54. ^ IRASTResolver new
  55. source: self source;
  56. yourself
  57. ! !
  58. AbstractCodeGenerator subclass: #FunCodeGenerator
  59. instanceVariableNames: 'stream nestedBlocks earlyReturn currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced argVariables'
  60. package: 'Compiler-Visitors'!
  61. !FunCodeGenerator methodsFor: 'accessing'!
  62. argVariables
  63. ^argVariables copy
  64. !
  65. knownVariables
  66. ^self pseudoVariables
  67. addAll: self tempVariables;
  68. addAll: self argVariables;
  69. yourself
  70. !
  71. tempVariables
  72. ^tempVariables copy
  73. !
  74. unknownVariables
  75. ^unknownVariables copy
  76. ! !
  77. !FunCodeGenerator methodsFor: 'compiling'!
  78. compileNode: aNode
  79. stream := '' writeStream.
  80. self visit: aNode.
  81. ^stream contents
  82. ! !
  83. !FunCodeGenerator methodsFor: 'initialization'!
  84. initialize
  85. super initialize.
  86. stream := '' writeStream.
  87. unknownVariables := #().
  88. tempVariables := #().
  89. argVariables := #().
  90. messageSends := #().
  91. classReferenced := #()
  92. ! !
  93. !FunCodeGenerator methodsFor: 'optimizations'!
  94. checkClass: aClassName for: receiver
  95. stream nextPutAll: '((($receiver = ', receiver, ').klass === smalltalk.', aClassName, ') ? '
  96. !
  97. inline: aSelector receiver: receiver argumentNodes: aCollection
  98. | inlined |
  99. inlined := false.
  100. "-- Booleans --"
  101. (aSelector = 'ifFalse:') ifTrue: [
  102. aCollection first isBlockNode ifTrue: [
  103. self checkClass: 'Boolean' for: receiver.
  104. stream nextPutAll: '(!! $receiver ? '.
  105. self visit: aCollection first.
  106. stream nextPutAll: '() : nil)'.
  107. inlined := true]].
  108. (aSelector = 'ifTrue:') ifTrue: [
  109. aCollection first isBlockNode ifTrue: [
  110. self checkClass: 'Boolean' for: receiver.
  111. stream nextPutAll: '($receiver ? '.
  112. self visit: aCollection first.
  113. stream nextPutAll: '() : nil)'.
  114. inlined := true]].
  115. (aSelector = 'ifTrue:ifFalse:') ifTrue: [
  116. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  117. self checkClass: 'Boolean' for: receiver.
  118. stream nextPutAll: '($receiver ? '.
  119. self visit: aCollection first.
  120. stream nextPutAll: '() : '.
  121. self visit: aCollection second.
  122. stream nextPutAll: '())'.
  123. inlined := true]].
  124. (aSelector = 'ifFalse:ifTrue:') ifTrue: [
  125. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  126. self checkClass: 'Boolean' for: receiver.
  127. stream nextPutAll: '(!! $receiver ? '.
  128. self visit: aCollection first.
  129. stream nextPutAll: '() : '.
  130. self visit: aCollection second.
  131. stream nextPutAll: '())'.
  132. inlined := true]].
  133. "-- Numbers --"
  134. (aSelector = '<') ifTrue: [
  135. self checkClass: 'Number' for: receiver.
  136. stream nextPutAll: '$receiver <'.
  137. self visit: aCollection first.
  138. inlined := true].
  139. (aSelector = '<=') ifTrue: [
  140. self checkClass: 'Number' for: receiver.
  141. stream nextPutAll: '$receiver <='.
  142. self visit: aCollection first.
  143. inlined := true].
  144. (aSelector = '>') ifTrue: [
  145. self checkClass: 'Number' for: receiver.
  146. stream nextPutAll: '$receiver >'.
  147. self visit: aCollection first.
  148. inlined := true].
  149. (aSelector = '>=') ifTrue: [
  150. self checkClass: 'Number' for: receiver.
  151. stream nextPutAll: '$receiver >='.
  152. self visit: aCollection first.
  153. inlined := true].
  154. (aSelector = '+') ifTrue: [
  155. self checkClass: 'Number' for: receiver.
  156. stream nextPutAll: '$receiver +'.
  157. self visit: aCollection first.
  158. inlined := true].
  159. (aSelector = '-') ifTrue: [
  160. self checkClass: 'Number' for: receiver.
  161. stream nextPutAll: '$receiver -'.
  162. self visit: aCollection first.
  163. inlined := true].
  164. (aSelector = '*') ifTrue: [
  165. self checkClass: 'Number' for: receiver.
  166. stream nextPutAll: '$receiver *'.
  167. self visit: aCollection first.
  168. inlined := true].
  169. (aSelector = '/') ifTrue: [
  170. self checkClass: 'Number' for: receiver.
  171. stream nextPutAll: '$receiver /'.
  172. self visit: aCollection first.
  173. inlined := true].
  174. ^inlined
  175. !
  176. inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
  177. | inlined |
  178. inlined := false.
  179. "-- BlockClosures --"
  180. (aSelector = 'whileTrue:') ifTrue: [
  181. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  182. stream nextPutAll: '(function(){while('.
  183. self visit: anObject.
  184. stream nextPutAll: '()) {'.
  185. self visit: aCollection first.
  186. stream nextPutAll: '()}})()'.
  187. inlined := true]].
  188. (aSelector = 'whileFalse:') ifTrue: [
  189. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  190. stream nextPutAll: '(function(){while(!!'.
  191. self visit: anObject.
  192. stream nextPutAll: '()) {'.
  193. self visit: aCollection first.
  194. stream nextPutAll: '()}})()'.
  195. inlined := true]].
  196. (aSelector = 'whileTrue') ifTrue: [
  197. anObject isBlockNode ifTrue: [
  198. stream nextPutAll: '(function(){while('.
  199. self visit: anObject.
  200. stream nextPutAll: '()) {}})()'.
  201. inlined := true]].
  202. (aSelector = 'whileFalse') ifTrue: [
  203. anObject isBlockNode ifTrue: [
  204. stream nextPutAll: '(function(){while(!!'.
  205. self visit: anObject.
  206. stream nextPutAll: '()) {}})()'.
  207. inlined := true]].
  208. "-- Numbers --"
  209. (aSelector = '+') ifTrue: [
  210. (self isNode: anObject ofClass: Number) ifTrue: [
  211. self visit: anObject.
  212. stream nextPutAll: ' + '.
  213. self visit: aCollection first.
  214. inlined := true]].
  215. (aSelector = '-') ifTrue: [
  216. (self isNode: anObject ofClass: Number) ifTrue: [
  217. self visit: anObject.
  218. stream nextPutAll: ' - '.
  219. self visit: aCollection first.
  220. inlined := true]].
  221. (aSelector = '*') ifTrue: [
  222. (self isNode: anObject ofClass: Number) ifTrue: [
  223. self visit: anObject.
  224. stream nextPutAll: ' * '.
  225. self visit: aCollection first.
  226. inlined := true]].
  227. (aSelector = '/') ifTrue: [
  228. (self isNode: anObject ofClass: Number) ifTrue: [
  229. self visit: anObject.
  230. stream nextPutAll: ' / '.
  231. self visit: aCollection first.
  232. inlined := true]].
  233. (aSelector = '<') ifTrue: [
  234. (self isNode: anObject ofClass: Number) ifTrue: [
  235. self visit: anObject.
  236. stream nextPutAll: ' < '.
  237. self visit: aCollection first.
  238. inlined := true]].
  239. (aSelector = '<=') ifTrue: [
  240. (self isNode: anObject ofClass: Number) ifTrue: [
  241. self visit: anObject.
  242. stream nextPutAll: ' <= '.
  243. self visit: aCollection first.
  244. inlined := true]].
  245. (aSelector = '>') ifTrue: [
  246. (self isNode: anObject ofClass: Number) ifTrue: [
  247. self visit: anObject.
  248. stream nextPutAll: ' > '.
  249. self visit: aCollection first.
  250. inlined := true]].
  251. (aSelector = '>=') ifTrue: [
  252. (self isNode: anObject ofClass: Number) ifTrue: [
  253. self visit: anObject.
  254. stream nextPutAll: ' >= '.
  255. self visit: aCollection first.
  256. inlined := true]].
  257. "-- UndefinedObject --"
  258. (aSelector = 'ifNil:') ifTrue: [
  259. aCollection first isBlockNode ifTrue: [
  260. stream nextPutAll: '(($receiver = '.
  261. self visit: anObject.
  262. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  263. self visit: aCollection first.
  264. stream nextPutAll: '() : $receiver'.
  265. inlined := true]].
  266. (aSelector = 'ifNotNil:') ifTrue: [
  267. aCollection first isBlockNode ifTrue: [
  268. stream nextPutAll: '(($receiver = '.
  269. self visit: anObject.
  270. stream nextPutAll: ') !!= nil && $receiver !!= undefined) ? '.
  271. self visit: aCollection first.
  272. stream nextPutAll: '() : nil'.
  273. inlined := true]].
  274. (aSelector = 'ifNil:ifNotNil:') ifTrue: [
  275. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  276. stream nextPutAll: '(($receiver = '.
  277. self visit: anObject.
  278. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  279. self visit: aCollection first.
  280. stream nextPutAll: '() : '.
  281. self visit: aCollection second.
  282. stream nextPutAll: '()'.
  283. inlined := true]].
  284. (aSelector = 'ifNotNil:ifNil:') ifTrue: [
  285. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  286. stream nextPutAll: '(($receiver = '.
  287. self visit: anObject.
  288. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  289. self visit: aCollection second.
  290. stream nextPutAll: '() : '.
  291. self visit: aCollection first.
  292. stream nextPutAll: '()'.
  293. inlined := true]].
  294. ^inlined
  295. !
  296. isNode: aNode ofClass: aClass
  297. ^aNode isValueNode and: [
  298. aNode value class = aClass or: [
  299. aNode value = 'self' and: [self currentClass = aClass]]]
  300. ! !
  301. !FunCodeGenerator methodsFor: 'testing'!
  302. performOptimizations
  303. ^self class performOptimizations
  304. ! !
  305. !FunCodeGenerator methodsFor: 'visiting'!
  306. send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
  307. ^String streamContents: [:str || tmp |
  308. tmp := stream.
  309. str nextPutAll: 'smalltalk.send('.
  310. str nextPutAll: aReceiver.
  311. str nextPutAll: ', "', aSelector asSelector, '", ['.
  312. stream := str.
  313. aCollection
  314. do: [:each | self visit: each]
  315. separatedBy: [stream nextPutAll: ', '].
  316. stream := tmp.
  317. str nextPutAll: ']'.
  318. aBoolean ifTrue: [
  319. str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass), '.superclass || nil'].
  320. str nextPutAll: ')']
  321. !
  322. visit: aNode
  323. aNode accept: self
  324. !
  325. visitAssignmentNode: aNode
  326. stream nextPutAll: '('.
  327. self visit: aNode left.
  328. stream nextPutAll: '='.
  329. self visit: aNode right.
  330. stream nextPutAll: ')'
  331. !
  332. visitBlockNode: aNode
  333. stream nextPutAll: '(function('.
  334. aNode parameters
  335. do: [:each |
  336. tempVariables add: each.
  337. stream nextPutAll: each]
  338. separatedBy: [stream nextPutAll: ', '].
  339. stream nextPutAll: '){'.
  340. aNode nodes do: [:each | self visit: each].
  341. stream nextPutAll: '})'
  342. !
  343. visitBlockSequenceNode: aNode
  344. | index |
  345. nestedBlocks := nestedBlocks + 1.
  346. aNode nodes isEmpty
  347. ifTrue: [
  348. stream nextPutAll: 'return nil;']
  349. ifFalse: [
  350. aNode temps do: [:each | | temp |
  351. temp := self safeVariableNameFor: each.
  352. tempVariables add: temp.
  353. stream nextPutAll: 'var ', temp, '=nil;'; lf].
  354. index := 0.
  355. aNode nodes do: [:each |
  356. index := index + 1.
  357. index = aNode nodes size ifTrue: [
  358. stream nextPutAll: 'return '].
  359. self visit: each.
  360. stream nextPutAll: ';']].
  361. nestedBlocks := nestedBlocks - 1
  362. !
  363. visitCascadeNode: aNode
  364. | index |
  365. index := 0.
  366. (tempVariables includes: '$rec') ifFalse: [
  367. tempVariables add: '$rec'].
  368. stream nextPutAll: '(function($rec){'.
  369. aNode nodes do: [:each |
  370. index := index + 1.
  371. index = aNode nodes size ifTrue: [
  372. stream nextPutAll: 'return '].
  373. each receiver: (VariableNode new value: '$rec').
  374. self visit: each.
  375. stream nextPutAll: ';'].
  376. stream nextPutAll: '})('.
  377. self visit: aNode receiver.
  378. stream nextPutAll: ')'
  379. !
  380. visitClassReferenceNode: aNode
  381. (referencedClasses includes: aNode value) ifFalse: [
  382. referencedClasses add: aNode value].
  383. stream nextPutAll: '(smalltalk.', aNode value, ' || ', aNode value, ')'
  384. !
  385. visitDynamicArrayNode: aNode
  386. stream nextPutAll: '['.
  387. aNode nodes
  388. do: [:each | self visit: each]
  389. separatedBy: [stream nextPutAll: ','].
  390. stream nextPutAll: ']'
  391. !
  392. visitDynamicDictionaryNode: aNode
  393. stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
  394. aNode nodes
  395. do: [:each | self visit: each]
  396. separatedBy: [stream nextPutAll: ','].
  397. stream nextPutAll: '])'
  398. !
  399. visitFailure: aFailure
  400. self error: aFailure asString
  401. !
  402. visitJSStatementNode: aNode
  403. stream nextPutAll: aNode source
  404. !
  405. visitMethodNode: aNode
  406. | str currentSelector |
  407. currentSelector := aNode selector asSelector.
  408. nestedBlocks := 0.
  409. earlyReturn := false.
  410. messageSends := #().
  411. referencedClasses := #().
  412. unknownVariables := #().
  413. tempVariables := #().
  414. argVariables := #().
  415. stream
  416. nextPutAll: 'smalltalk.method({'; lf;
  417. nextPutAll: 'selector: "', aNode selector, '",'; lf.
  418. stream nextPutAll: 'source: ', self source asJavascript, ',';lf.
  419. stream nextPutAll: 'fn: function('.
  420. aNode arguments
  421. do: [:each |
  422. argVariables add: each.
  423. stream nextPutAll: each]
  424. separatedBy: [stream nextPutAll: ', '].
  425. stream
  426. nextPutAll: '){'; lf;
  427. nextPutAll: 'var self=this;'; lf.
  428. str := stream.
  429. stream := '' writeStream.
  430. aNode nodes do: [:each |
  431. self visit: each].
  432. earlyReturn ifTrue: [
  433. str nextPutAll: 'var $early={};'; lf; nextPutAll: 'try{'].
  434. str nextPutAll: stream contents.
  435. stream := str.
  436. stream
  437. lf;
  438. nextPutAll: 'return self;'.
  439. earlyReturn ifTrue: [
  440. stream lf; nextPutAll: '} catch(e) {if(e===$early)return e[0]; throw e}'].
  441. stream nextPutAll: '}'.
  442. stream
  443. nextPutAll: ',', String lf, 'messageSends: ';
  444. nextPutAll: messageSends asJavascript, ','; lf;
  445. nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
  446. nextPutAll: 'referencedClasses: ['.
  447. referencedClasses
  448. do: [:each | stream nextPutAll: each printString]
  449. separatedBy: [stream nextPutAll: ','].
  450. stream nextPutAll: ']'.
  451. stream nextPutAll: '})'
  452. !
  453. visitReturnNode: aNode
  454. nestedBlocks > 0 ifTrue: [
  455. earlyReturn := true].
  456. nestedBlocks > 0
  457. ifTrue: [
  458. stream
  459. nextPutAll: '(function(){throw $early=[']
  460. ifFalse: [stream nextPutAll: 'return '].
  461. aNode nodes do: [:each |
  462. self visit: each].
  463. nestedBlocks > 0 ifTrue: [
  464. stream nextPutAll: ']})()']
  465. !
  466. visitSendNode: aNode
  467. | str receiver superSend inlined |
  468. str := stream.
  469. (messageSends includes: aNode selector) ifFalse: [
  470. messageSends add: aNode selector].
  471. stream := '' writeStream.
  472. self visit: aNode receiver.
  473. superSend := stream contents = 'super'.
  474. receiver := superSend ifTrue: ['self'] ifFalse: [stream contents].
  475. stream := str.
  476. self performOptimizations
  477. ifTrue: [
  478. (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifFalse: [
  479. (self inline: aNode selector receiver: receiver argumentNodes: aNode arguments)
  480. ifTrue: [stream nextPutAll: ' : ', (self send: aNode selector to: '$receiver' arguments: aNode arguments superSend: superSend), ')']
  481. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]]]
  482. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]
  483. !
  484. visitSequenceNode: aNode
  485. aNode temps do: [:each || temp |
  486. temp := self safeVariableNameFor: each.
  487. tempVariables add: temp.
  488. stream nextPutAll: 'var ', temp, '=nil;'; lf].
  489. aNode nodes do: [:each |
  490. self visit: each.
  491. stream nextPutAll: ';']
  492. separatedBy: [stream lf]
  493. !
  494. visitValueNode: aNode
  495. stream nextPutAll: aNode value asJavascript
  496. !
  497. visitVariableNode: aNode
  498. | varName |
  499. (self currentClass allInstanceVariableNames includes: aNode value)
  500. ifTrue: [stream nextPutAll: 'self[''@', aNode value, ''']']
  501. ifFalse: [
  502. varName := self safeVariableNameFor: aNode value.
  503. (self knownVariables includes: varName)
  504. ifFalse: [
  505. unknownVariables add: aNode value.
  506. aNode assigned
  507. ifTrue: [stream nextPutAll: varName]
  508. ifFalse: [stream nextPutAll: '(typeof ', varName, ' == ''undefined'' ? nil : ', varName, ')']]
  509. ifTrue: [
  510. aNode value = 'thisContext'
  511. ifTrue: [stream nextPutAll: '(smalltalk.getThisContext())']
  512. ifFalse: [stream nextPutAll: varName]]]
  513. ! !
  514. FunCodeGenerator class instanceVariableNames: 'performOptimizations'!
  515. !FunCodeGenerator class methodsFor: 'accessing'!
  516. performOptimizations
  517. ^performOptimizations ifNil: [true]
  518. !
  519. performOptimizations: aBoolean
  520. performOptimizations := aBoolean
  521. ! !
  522. AbstractCodeGenerator subclass: #ImpCodeGenerator
  523. instanceVariableNames: 'stream nestedBlocks earlyReturn currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced argVariables mutables target lazyVars realVarNames'
  524. package: 'Compiler-Visitors'!
  525. !ImpCodeGenerator methodsFor: 'accessing'!
  526. argVariables
  527. ^argVariables copy
  528. !
  529. knownVariables
  530. ^self pseudoVariables
  531. addAll: self tempVariables;
  532. addAll: self argVariables;
  533. yourself
  534. !
  535. tempVariables
  536. ^tempVariables copy
  537. !
  538. unknownVariables
  539. ^unknownVariables copy
  540. ! !
  541. !ImpCodeGenerator methodsFor: 'compilation DSL'!
  542. aboutToModifyState
  543. | list old |
  544. list := mutables.
  545. mutables := Set new.
  546. old := self switchTarget: nil.
  547. list do: [ :each | | value |
  548. self switchTarget: each.
  549. self realAssign: (lazyVars at: each)
  550. ].
  551. self switchTarget: old
  552. !
  553. ifValueWanted: aBlock
  554. target ifNotNil: aBlock
  555. !
  556. isolated: node
  557. ^ self visit: node targetBeing: self nextLazyvarName
  558. !
  559. isolatedUse: node
  560. | old |
  561. old := self switchTarget: self nextLazyvarName.
  562. self visit: node.
  563. ^self useValueNamed: (self switchTarget: old)
  564. !
  565. lazyAssign: aString dependsOnState: aBoolean
  566. (lazyVars includesKey: target)
  567. ifTrue: [ lazyVars at: target put: aString. aBoolean ifTrue: [ mutables add: target ] ]
  568. ifFalse: [ self realAssign: aString ]
  569. !
  570. lazyAssignExpression: aString
  571. self lazyAssign: aString dependsOnState: true
  572. !
  573. lazyAssignValue: aString
  574. self lazyAssign: aString dependsOnState: false
  575. !
  576. makeTargetRealVariable
  577. (lazyVars includesKey: target) ifTrue: [
  578. lazyVars removeKey: target.
  579. lazyVars at: 'assigned ',target put: nil. "<-- only to retain size, it is used in nextLazyvarName"
  580. realVarNames add: target ].
  581. !
  582. nextLazyvarName
  583. | name |
  584. name := '$', lazyVars size asString.
  585. lazyVars at: name put: name.
  586. ^name
  587. !
  588. nilIfValueWanted
  589. target ifNotNil: [ self lazyAssignValue: 'nil' ]
  590. !
  591. realAssign: aString
  592. | closer |
  593. aString ifNotEmpty: [
  594. self aboutToModifyState.
  595. closer := ''.
  596. self ifValueWanted: [ stream nextPutAll:
  597. (target = '^' ifTrue: ['return '] ifFalse: [
  598. target = '!!' ifTrue: [ closer := ']'. 'throw $early=['] ifFalse: [
  599. target, '=']]) ].
  600. self makeTargetRealVariable.
  601. stream nextPutAll: aString, closer, ';', self mylf ]
  602. !
  603. switchTarget: aString
  604. | old |
  605. old := target.
  606. target := aString.
  607. ^old
  608. !
  609. useValueNamed: key
  610. | val |
  611. (realVarNames includes: key) ifTrue: [ ^key ].
  612. mutables remove: key.
  613. ^lazyVars at: key
  614. !
  615. visit: aNode targetBeing: aString
  616. | old |
  617. old := self switchTarget: aString.
  618. self visit: aNode.
  619. ^ self switchTarget: old.
  620. ! !
  621. !ImpCodeGenerator methodsFor: 'compiling'!
  622. compileNode: aNode
  623. stream := '' writeStream.
  624. self visit: aNode.
  625. ^stream contents
  626. ! !
  627. !ImpCodeGenerator methodsFor: 'initialization'!
  628. initialize
  629. super initialize.
  630. stream := '' writeStream.
  631. unknownVariables := #().
  632. tempVariables := #().
  633. argVariables := #().
  634. messageSends := #().
  635. classReferenced := #().
  636. mutables := Set new.
  637. realVarNames := Set new.
  638. lazyVars := HashedCollection new.
  639. target := nil
  640. ! !
  641. !ImpCodeGenerator methodsFor: 'optimizations'!
  642. checkClass: aClassName for: receiver
  643. self prvCheckClass: aClassName for: receiver.
  644. stream nextPutAll: '{'
  645. !
  646. checkClass: aClassName for: receiver includeIf: aBoolean
  647. self prvCheckClass: aClassName for: receiver.
  648. stream nextPutAll: (aBoolean ifTrue: ['if(('] ifFalse: ['if(!!(']), (self useValueNamed: receiver), ')) {'
  649. !
  650. inline: aSelector receiver: receiver argumentNodes: aCollection
  651. "-- Booleans --"
  652. (aSelector = 'ifFalse:') ifTrue: [
  653. aCollection first isBlockNode ifTrue: [
  654. self checkClass: 'Boolean' for: receiver includeIf: false.
  655. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  656. self prvPutAndElse: [ self nilIfValueWanted ].
  657. ^true]].
  658. (aSelector = 'ifTrue:') ifTrue: [
  659. aCollection first isBlockNode ifTrue: [
  660. self checkClass: 'Boolean' for: receiver includeIf: true.
  661. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  662. self prvPutAndElse: [ self nilIfValueWanted ].
  663. ^true]].
  664. (aSelector = 'ifTrue:ifFalse:') ifTrue: [
  665. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  666. self checkClass: 'Boolean' for: receiver includeIf: true.
  667. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  668. self prvPutAndElse: [ self visit: aCollection second nodes first ].
  669. ^true]].
  670. (aSelector = 'ifFalse:ifTrue:') ifTrue: [
  671. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  672. self checkClass: 'Boolean' for: receiver includeIf: false.
  673. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  674. self prvPutAndElse: [ self visit: aCollection second nodes first ].
  675. ^true]].
  676. "-- Numbers --"
  677. (aSelector = '<') ifTrue: [ | operand |
  678. operand := self isolatedUse: aCollection first.
  679. self checkClass: 'Number' for: receiver.
  680. self prvPutAndElse: [
  681. self lazyAssignExpression: '(', (self useValueNamed: receiver), '<', operand, ')' ].
  682. ^{ VerbatimNode new value: operand }].
  683. (aSelector = '<=') ifTrue: [ | operand |
  684. operand := self isolatedUse: aCollection first.
  685. self checkClass: 'Number' for: receiver.
  686. self prvPutAndElse: [
  687. self lazyAssignExpression: '(', (self useValueNamed: receiver), '<=', operand, ')' ].
  688. ^{ VerbatimNode new value: operand }].
  689. (aSelector = '>') ifTrue: [ | operand |
  690. operand := self isolatedUse: aCollection first.
  691. self checkClass: 'Number' for: receiver.
  692. self prvPutAndElse: [
  693. self lazyAssignExpression: '(', (self useValueNamed: receiver), '>', operand, ')' ].
  694. ^{ VerbatimNode new value: operand }].
  695. (aSelector = '>=') ifTrue: [ | operand |
  696. operand := self isolatedUse: aCollection first.
  697. self checkClass: 'Number' for: receiver.
  698. self prvPutAndElse: [
  699. self lazyAssignExpression: '(', (self useValueNamed: receiver), '>=', operand, ')' ].
  700. ^{ VerbatimNode new value: operand }].
  701. (aSelector = '+') ifTrue: [ | operand |
  702. operand := self isolatedUse: aCollection first.
  703. self checkClass: 'Number' for: receiver.
  704. self prvPutAndElse: [
  705. self lazyAssignExpression: '(', (self useValueNamed: receiver), '+', operand, ')' ].
  706. ^{ VerbatimNode new value: operand }].
  707. (aSelector = '-') ifTrue: [ | operand |
  708. operand := self isolatedUse: aCollection first.
  709. self checkClass: 'Number' for: receiver.
  710. self prvPutAndElse: [
  711. self lazyAssignExpression: '(', (self useValueNamed: receiver), '-', operand, ')' ].
  712. ^{ VerbatimNode new value: operand }].
  713. (aSelector = '*') ifTrue: [ | operand |
  714. operand := self isolatedUse: aCollection first.
  715. self checkClass: 'Number' for: receiver.
  716. self prvPutAndElse: [
  717. self lazyAssignExpression: '(', (self useValueNamed: receiver), '*', operand, ')' ].
  718. ^{ VerbatimNode new value: operand }].
  719. (aSelector = '/') ifTrue: [ | operand |
  720. operand := self isolatedUse: aCollection first.
  721. self checkClass: 'Number' for: receiver.
  722. self prvPutAndElse: [
  723. self lazyAssignExpression: '(', (self useValueNamed: receiver), '/', operand, ')' ].
  724. ^{ VerbatimNode new value: operand }].
  725. ^nil
  726. !
  727. inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
  728. | inlined |
  729. inlined := false.
  730. "-- BlockClosures --"
  731. (aSelector = 'whileTrue:') ifTrue: [
  732. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [ | old |
  733. self prvWhileConditionStatement: 'for(;;){' pre: 'if (!!(' condition: anObject post: ')) {'.
  734. stream nextPutAll: 'break}', self mylf.
  735. self prvPutAndClose: [ self visit: aCollection first nodes first targetBeing: nil ].
  736. inlined := true]].
  737. (aSelector = 'whileFalse:') ifTrue: [
  738. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [ | old |
  739. self prvWhileConditionStatement: 'for(;;){' pre: 'if ((' condition: anObject post: ')) {'.
  740. stream nextPutAll: 'break}', self mylf.
  741. self prvPutAndClose: [ self visit: aCollection first nodes first targetBeing: nil ].
  742. inlined := true]].
  743. (aSelector = 'whileTrue') ifTrue: [
  744. anObject isBlockNode ifTrue: [
  745. self prvWhileConditionStatement: 'do{' pre: '}while((' condition: anObject post: '));', self mylf.
  746. inlined := true]].
  747. (aSelector = 'whileFalse') ifTrue: [
  748. anObject isBlockNode ifTrue: [
  749. self prvWhileConditionStatement: 'do{' pre: '}while(!!(' condition: anObject post: '));', self mylf.
  750. inlined := true]].
  751. "-- Numbers --"
  752. (#('+' '-' '*' '/' '<' '<=' '>=' '>') includes: aSelector) ifTrue: [
  753. (self prvInlineNumberOperator: aSelector on: anObject and: aCollection first) ifTrue: [
  754. inlined := true]].
  755. "-- UndefinedObject --"
  756. (aSelector = 'ifNil:') ifTrue: [
  757. aCollection first isBlockNode ifTrue: [ | rcv |
  758. self aboutToModifyState.
  759. rcv := self isolatedUse: anObject.
  760. rcv = 'super' ifTrue: [ rcv := 'self' ].
  761. self makeTargetRealVariable.
  762. stream nextPutAll: 'if((', rcv, ') === nil || (', rcv, ') == null) {'.
  763. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  764. self prvPutAndClose: [ self lazyAssignValue: rcv ].
  765. inlined := true]].
  766. (aSelector = 'ifNotNil:') ifTrue: [
  767. aCollection first isBlockNode ifTrue: [ | rcv |
  768. self aboutToModifyState.
  769. rcv := self isolatedUse: anObject.
  770. rcv = 'super' ifTrue: [ rcv := 'self' ].
  771. self makeTargetRealVariable.
  772. stream nextPutAll: 'if((', rcv, ') !!== nil && (', rcv, ') !!= null) {'.
  773. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  774. self prvPutAndClose: [ self lazyAssignValue: rcv ].
  775. inlined := true]].
  776. (aSelector = 'ifNil:ifNotNil:') ifTrue: [
  777. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [ | rcv |
  778. self aboutToModifyState.
  779. rcv := self isolatedUse: anObject.
  780. rcv = 'super' ifTrue: [ rcv := 'self' ].
  781. self makeTargetRealVariable.
  782. stream nextPutAll: 'if((', rcv, ') === nil || (', rcv, ') == null) {'.
  783. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  784. self prvPutAndClose: [ self visit: aCollection second nodes first ].
  785. inlined := true]].
  786. (aSelector = 'ifNotNil:ifNil:') ifTrue: [
  787. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [ | rcv |
  788. self aboutToModifyState.
  789. rcv := self isolatedUse: anObject.
  790. rcv = 'super' ifTrue: [ rcv := 'self' ].
  791. self makeTargetRealVariable.
  792. stream nextPutAll: 'if((', rcv, ') !!== nil && (', rcv, ') !!= null) {'.
  793. self prvPutAndElse: [ self visit: aCollection first nodes first ].
  794. self prvPutAndClose: [ self visit: aCollection second nodes first ].
  795. inlined := true]].
  796. (aSelector = 'isNil') ifTrue: [ | rcv |
  797. rcv := self isolatedUse: anObject.
  798. rcv = 'super' ifTrue: [ rcv := 'self' ].
  799. self lazyAssignValue: '((', rcv, ') === nil || (', rcv, ') == null)'.
  800. inlined := true].
  801. (aSelector = 'notNil') ifTrue: [ | rcv |
  802. rcv := self isolatedUse: anObject.
  803. rcv = 'super' ifTrue: [ rcv := 'self' ].
  804. self lazyAssignValue: '((', rcv, ') !!== nil && (', rcv, ') !!= null)'.
  805. inlined := true].
  806. ^inlined
  807. !
  808. isNode: aNode ofClass: aClass
  809. ^aNode isValueNode and: [
  810. aNode value class = aClass or: [
  811. aNode value = 'self' and: [self currentClass = aClass]]]
  812. !
  813. prvCheckClass: aClassName for: receiver
  814. self makeTargetRealVariable.
  815. self aboutToModifyState.
  816. stream nextPutAll: 'if((', (self useValueNamed: receiver), ').klass === smalltalk.', aClassName, ') '
  817. !
  818. prvInlineNumberOperator: aSelector on: receiverNode and: operandNode
  819. (aSelector = aSelector) ifTrue: [
  820. (self isNode: receiverNode ofClass: Number) ifTrue: [
  821. | rcv operand |
  822. rcv := self isolated: receiverNode.
  823. operand := self isolated: operandNode.
  824. self lazyAssignValue: ((self useValueNamed: rcv), aSelector, (self useValueNamed: operand)).
  825. ^true]].
  826. ^false
  827. !
  828. prvWhileConditionStatement: stmtString pre: preString condition: anObject post: postString
  829. | x |
  830. stream nextPutAll: stmtString.
  831. x := self isolatedUse: anObject nodes first.
  832. x ifEmpty: [ x := '"should not reach - receiver includes ^"' ].
  833. stream nextPutAll: preString, x, postString.
  834. self nilIfValueWanted
  835. ! !
  836. !ImpCodeGenerator methodsFor: 'output'!
  837. mylf
  838. ^String lf, ((Array new: nestedBlocks+2) join: String tab)
  839. !
  840. prvPutAndClose: aBlock
  841. aBlock value.
  842. stream nextPutAll: '}', self mylf
  843. !
  844. prvPutAndElse: aBlock
  845. aBlock value.
  846. stream nextPutAll: '} else {'
  847. !
  848. putTemps: temps
  849. temps ifNotEmpty: [
  850. stream nextPutAll: 'var '.
  851. temps do: [:each | | temp |
  852. temp := self safeVariableNameFor: each.
  853. tempVariables add: temp.
  854. stream nextPutAll: temp, '=nil'] separatedBy: [ stream nextPutAll: ',' ].
  855. stream nextPutAll: ';', self mylf
  856. ]
  857. ! !
  858. !ImpCodeGenerator methodsFor: 'testing'!
  859. assert: aBoolean
  860. aBoolean ifFalse: [ self error: 'assertion failed' ]
  861. !
  862. performOptimizations
  863. ^self class performOptimizations
  864. ! !
  865. !ImpCodeGenerator methodsFor: 'visiting'!
  866. send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
  867. | args |
  868. args := self isolated: (DynamicArrayNode new nodes: aCollection; yourself).
  869. self lazyAssignExpression: (String streamContents: [ :str |
  870. str nextPutAll: 'smalltalk.send('.
  871. str nextPutAll: (self useValueNamed: aReceiver).
  872. str nextPutAll: ', "', aSelector asSelector, '", '.
  873. str nextPutAll: (self useValueNamed: args).
  874. aBoolean ifTrue: [
  875. str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass superclass)].
  876. str nextPutAll: ')'
  877. ])
  878. !
  879. sequenceOfNodes: nodes temps: temps
  880. nodes isEmpty
  881. ifFalse: [ | old index |
  882. self putTemps: temps.
  883. old :=self switchTarget: nil.
  884. index := 0.
  885. nodes do: [:each |
  886. index := index + 1.
  887. index = nodes size ifTrue: [ self switchTarget: old ].
  888. self visit: each ]]
  889. ifTrue: [ self nilIfValueWanted ]
  890. !
  891. visit: aNode
  892. aNode accept: self
  893. !
  894. visitAssignmentNode: aNode
  895. | olds oldt |
  896. olds := stream.
  897. stream := '' writeStream.
  898. oldt := self switchTarget: self nextLazyvarName.
  899. self visit: aNode left.
  900. self assert: (lazyVars at: target) ~= target.
  901. self switchTarget: (self useValueNamed: (self switchTarget: nil)).
  902. self assert: (lazyVars includesKey: target) not.
  903. stream := olds.
  904. self visit: aNode right.
  905. olds := self switchTarget: oldt.
  906. self ifValueWanted: [ self lazyAssignExpression: olds ]
  907. !
  908. visitBlockNode: aNode
  909. | oldt olds oldm |
  910. self assert: aNode nodes size = 1.
  911. oldt := self switchTarget: '^'.
  912. olds := stream.
  913. stream := '' writeStream.
  914. stream nextPutAll: '(function('.
  915. aNode parameters
  916. do: [:each |
  917. tempVariables add: each.
  918. stream nextPutAll: each]
  919. separatedBy: [stream nextPutAll: ', '].
  920. stream nextPutAll: '){'.
  921. nestedBlocks := nestedBlocks + 1.
  922. oldm := mutables.
  923. mutables := Set new.
  924. self visit: aNode nodes first.
  925. self assert: mutables isEmpty.
  926. mutables := oldm.
  927. nestedBlocks := nestedBlocks - 1.
  928. stream nextPutAll: '})'.
  929. self switchTarget: oldt.
  930. oldt := stream contents.
  931. stream := olds.
  932. self lazyAssignExpression: oldt
  933. !
  934. visitBlockSequenceNode: aNode
  935. self sequenceOfNodes: aNode nodes temps: aNode temps
  936. !
  937. visitCascadeNode: aNode
  938. | rcv |
  939. rcv := self isolated: aNode receiver.
  940. self aboutToModifyState.
  941. rcv := self useValueNamed: rcv.
  942. aNode nodes do: [:each |
  943. each receiver: (VerbatimNode new value: rcv) ].
  944. self sequenceOfNodes: aNode nodes temps: #()
  945. !
  946. visitClassReferenceNode: aNode
  947. (referencedClasses includes: aNode value) ifFalse: [
  948. referencedClasses add: aNode value].
  949. self lazyAssignExpression: '(smalltalk.', aNode value, ' || ', aNode value, ')'
  950. !
  951. visitDynamicArrayNode: aNode
  952. | args |
  953. args :=aNode nodes collect: [ :node | self isolated: node ].
  954. self lazyAssignValue: (String streamContents: [ :str |
  955. str nextPutAll: '['.
  956. args
  957. do: [:each | str nextPutAll: (self useValueNamed: each) ]
  958. separatedBy: [str nextPutAll: ', '].
  959. str nextPutAll: ']'
  960. ])
  961. !
  962. visitDynamicDictionaryNode: aNode
  963. | elements |
  964. elements := self isolated: (DynamicArrayNode new nodes: aNode nodes; yourself).
  965. self lazyAssignValue: 'smalltalk.HashedCollection._fromPairs_(', (self useValueNamed: elements), ')'
  966. !
  967. visitFailure: aFailure
  968. self error: aFailure asString
  969. !
  970. visitJSStatementNode: aNode
  971. self aboutToModifyState.
  972. stream nextPutAll: ';', (aNode source replace: '>>' with: '>'), ';', self mylf
  973. !
  974. visitMethodNode: aNode
  975. | str currentSelector |
  976. currentSelector := aNode selector asSelector.
  977. nestedBlocks := 0.
  978. earlyReturn := false.
  979. messageSends := #().
  980. referencedClasses := #().
  981. unknownVariables := #().
  982. tempVariables := #().
  983. argVariables := #().
  984. lazyVars := HashedCollection new.
  985. mutables := Set new.
  986. realVarNames := Set new.
  987. stream
  988. nextPutAll: 'smalltalk.method({'; lf;
  989. nextPutAll: 'selector: "', aNode selector, '",'; lf.
  990. stream nextPutAll: 'source: ', self source asJavascript, ',';lf.
  991. stream nextPutAll: 'fn: function('.
  992. aNode arguments
  993. do: [:each |
  994. argVariables add: each.
  995. stream nextPutAll: each]
  996. separatedBy: [stream nextPutAll: ', '].
  997. stream
  998. nextPutAll: '){var self=this;', self mylf.
  999. str := stream.
  1000. stream := '' writeStream.
  1001. self switchTarget: nil.
  1002. self assert: aNode nodes size = 1.
  1003. self visit: aNode nodes first.
  1004. realVarNames ifNotEmpty: [ str nextPutAll: 'var ', (realVarNames asArray join: ','), ';', self mylf ].
  1005. earlyReturn ifTrue: [
  1006. str nextPutAll: 'var $early={}; try{', self mylf].
  1007. str nextPutAll: stream contents.
  1008. stream := str.
  1009. (aNode nodes first nodes notEmpty and: [ |checker|
  1010. checker := ReturnNodeChecker new.
  1011. checker visit: aNode nodes first nodes last.
  1012. checker wasReturnNode]) ifFalse: [ self switchTarget: '^'. self lazyAssignValue: 'self'. self switchTarget: nil ].
  1013. earlyReturn ifTrue: [
  1014. stream nextPutAll: '} catch(e) {if(e===$early) return e[0]; throw e}'].
  1015. stream nextPutAll: '}'.
  1016. stream
  1017. nextPutAll: ',', String lf, 'messageSends: ';
  1018. nextPutAll: messageSends asJavascript, ','; lf;
  1019. nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
  1020. nextPutAll: 'referencedClasses: ['.
  1021. referencedClasses
  1022. do: [:each | stream nextPutAll: each printString]
  1023. separatedBy: [stream nextPutAll: ','].
  1024. stream nextPutAll: ']'.
  1025. stream nextPutAll: '})'.
  1026. self assert: mutables isEmpty
  1027. !
  1028. visitReturnNode: aNode
  1029. self assert: aNode nodes size = 1.
  1030. nestedBlocks > 0 ifTrue: [
  1031. earlyReturn := true].
  1032. self
  1033. visit: aNode nodes first
  1034. targetBeing: (nestedBlocks > 0 ifTrue: ['!!'] ifFalse: ['^']).
  1035. self lazyAssignValue: ''
  1036. !
  1037. visitSendNode: aNode
  1038. | receiver superSend rcv |
  1039. (messageSends includes: aNode selector) ifFalse: [
  1040. messageSends add: aNode selector].
  1041. self performOptimizations
  1042. ifTrue: [
  1043. (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifTrue: [ ^self ].
  1044. ].
  1045. rcv := self isolated: aNode receiver.
  1046. superSend := (lazyVars at: rcv ifAbsent: []) = 'super'.
  1047. superSend ifTrue: [ mutables remove: rcv. lazyVars at: rcv put: 'self' ].
  1048. self performOptimizations
  1049. ifTrue: [ | inline |
  1050. inline := self inline: aNode selector receiver: rcv argumentNodes: aNode arguments.
  1051. inline ifNotNil: [ | args |
  1052. args := inline = true ifTrue: [ aNode arguments ] ifFalse: [ inline ].
  1053. self prvPutAndClose: [ self send: aNode selector to: rcv arguments: args superSend: superSend ].
  1054. ^self ]].
  1055. self send: aNode selector to: rcv arguments: aNode arguments superSend: superSend
  1056. !
  1057. visitSequenceNode: aNode
  1058. aNode nodes isEmpty ifFalse: [
  1059. self sequenceOfNodes: aNode nodes temps: aNode temps ]
  1060. !
  1061. visitValueNode: aNode
  1062. self lazyAssignValue: aNode value asJavascript
  1063. !
  1064. visitVariableNode: aNode
  1065. | varName |
  1066. (self currentClass allInstanceVariableNames includes: aNode value)
  1067. ifTrue: [self lazyAssignExpression: 'self[''@', aNode value, ''']']
  1068. ifFalse: [
  1069. varName := self safeVariableNameFor: aNode value.
  1070. (self knownVariables includes: varName)
  1071. ifFalse: [
  1072. unknownVariables add: aNode value.
  1073. aNode assigned
  1074. ifTrue: [self lazyAssignExpression: varName]
  1075. ifFalse: [self lazyAssignExpression: '(typeof ', varName, ' == ''undefined'' ? nil : ', varName, ')']]
  1076. ifTrue: [
  1077. aNode value = 'thisContext'
  1078. ifTrue: [self lazyAssignExpression: '(smalltalk.getThisContext())']
  1079. ifFalse: [(self pseudoVariables includes: varName)
  1080. ifTrue: [ self lazyAssignValue: varName ]
  1081. ifFalse: [ self lazyAssignExpression: varName]]]]
  1082. !
  1083. visitVerbatimNode: aNode
  1084. self lazyAssignValue: aNode value
  1085. ! !
  1086. ImpCodeGenerator class instanceVariableNames: 'performOptimizations'!
  1087. !ImpCodeGenerator class methodsFor: 'accessing'!
  1088. performOptimizations
  1089. ^performOptimizations ifNil: [true]
  1090. !
  1091. performOptimizations: aBoolean
  1092. performOptimizations := aBoolean
  1093. ! !
  1094. NodeVisitor subclass: #ReturnNodeChecker
  1095. instanceVariableNames: 'wasReturnNode'
  1096. package: 'Compiler-Visitors'!
  1097. !ReturnNodeChecker methodsFor: 'accessing'!
  1098. wasReturnNode
  1099. ^wasReturnNode
  1100. ! !
  1101. !ReturnNodeChecker methodsFor: 'initializing'!
  1102. initialize
  1103. wasReturnNode := false
  1104. ! !
  1105. !ReturnNodeChecker methodsFor: 'visiting'!
  1106. visitReturnNode: aNode
  1107. wasReturnNode := true
  1108. ! !