Compiler.st 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. Object subclass: #Node
  2. instanceVariableNames: 'nodes'
  3. category: 'Compiler'!
  4. !Node methodsFor: 'accessing'!
  5. nodes
  6. ^nodes ifNil: [nodes := Array new]
  7. !
  8. addNode: aNode
  9. self nodes add: aNode
  10. ! !
  11. !Node methodsFor: 'building'!
  12. nodes: aCollection
  13. nodes := aCollection
  14. ! !
  15. !Node methodsFor: 'testing'!
  16. isValueNode
  17. ^false
  18. !
  19. isBlockNode
  20. ^false
  21. !
  22. isBlockSequenceNode
  23. ^false
  24. ! !
  25. !Node methodsFor: 'visiting'!
  26. accept: aVisitor
  27. aVisitor visitNode: self
  28. ! !
  29. Node subclass: #MethodNode
  30. instanceVariableNames: 'selector arguments source'
  31. category: 'Compiler'!
  32. !MethodNode methodsFor: 'accessing'!
  33. selector
  34. ^selector
  35. !
  36. selector: aString
  37. selector := aString
  38. !
  39. arguments
  40. ^arguments ifNil: [#()]
  41. !
  42. arguments: aCollection
  43. arguments := aCollection
  44. !
  45. source
  46. ^source
  47. !
  48. source: aString
  49. source := aString
  50. ! !
  51. !MethodNode methodsFor: 'visiting'!
  52. accept: aVisitor
  53. aVisitor visitMethodNode: self
  54. ! !
  55. Node subclass: #SendNode
  56. instanceVariableNames: 'selector arguments receiver'
  57. category: 'Compiler'!
  58. !SendNode methodsFor: 'accessing'!
  59. selector
  60. ^selector
  61. !
  62. selector: aString
  63. selector := aString
  64. !
  65. arguments
  66. ^arguments ifNil: [arguments := #()]
  67. !
  68. arguments: aCollection
  69. arguments := aCollection
  70. !
  71. receiver
  72. ^receiver
  73. !
  74. receiver: aNode
  75. receiver := aNode
  76. !
  77. valueForReceiver: anObject
  78. ^SendNode new
  79. receiver: (self receiver
  80. ifNil: [anObject]
  81. ifNotNil: [self receiver valueForReceiver: anObject]);
  82. selector: self selector;
  83. arguments: self arguments;
  84. yourself
  85. !
  86. cascadeNodeWithMessages: aCollection
  87. | first |
  88. first := SendNode new
  89. selector: self selector;
  90. arguments: self arguments;
  91. yourself.
  92. ^CascadeNode new
  93. receiver: self receiver;
  94. nodes: (Array with: first), aCollection;
  95. yourself
  96. ! !
  97. !SendNode methodsFor: 'visiting'!
  98. accept: aVisitor
  99. aVisitor visitSendNode: self
  100. ! !
  101. Node subclass: #CascadeNode
  102. instanceVariableNames: 'receiver'
  103. category: 'Compiler'!
  104. !CascadeNode methodsFor: 'accessing'!
  105. receiver
  106. ^receiver
  107. !
  108. receiver: aNode
  109. receiver := aNode
  110. ! !
  111. !CascadeNode methodsFor: 'visiting'!
  112. accept: aVisitor
  113. aVisitor visitCascadeNode: self
  114. ! !
  115. Node subclass: #AssignmentNode
  116. instanceVariableNames: 'left right'
  117. category: 'Compiler'!
  118. !AssignmentNode methodsFor: 'accessing'!
  119. left
  120. ^left
  121. !
  122. left: aNode
  123. left := aNode.
  124. left assigned: true
  125. !
  126. right
  127. ^right
  128. !
  129. right: aNode
  130. right := aNode
  131. ! !
  132. !AssignmentNode methodsFor: 'visiting'!
  133. accept: aVisitor
  134. aVisitor visitAssignmentNode: self
  135. ! !
  136. Node subclass: #BlockNode
  137. instanceVariableNames: 'parameters inlined'
  138. category: 'Compiler'!
  139. !BlockNode methodsFor: 'accessing'!
  140. parameters
  141. ^parameters ifNil: [parameters := Array new]
  142. !
  143. parameters: aCollection
  144. parameters := aCollection
  145. !
  146. inlined
  147. ^inlined ifNil: [false]
  148. !
  149. inlined: aBoolean
  150. inlined := aBoolean
  151. ! !
  152. !BlockNode methodsFor: 'testing'!
  153. isBlockNode
  154. ^true
  155. ! !
  156. !BlockNode methodsFor: 'visiting'!
  157. accept: aVisitor
  158. aVisitor visitBlockNode: self
  159. ! !
  160. Node subclass: #SequenceNode
  161. instanceVariableNames: 'temps'
  162. category: 'Compiler'!
  163. !SequenceNode methodsFor: 'accessing'!
  164. temps
  165. ^temps ifNil: [#()]
  166. !
  167. temps: aCollection
  168. temps := aCollection
  169. ! !
  170. !SequenceNode methodsFor: 'testing'!
  171. asBlockSequenceNode
  172. ^BlockSequenceNode new
  173. nodes: self nodes;
  174. temps: self temps;
  175. yourself
  176. ! !
  177. !SequenceNode methodsFor: 'visiting'!
  178. accept: aVisitor
  179. aVisitor visitSequenceNode: self
  180. ! !
  181. SequenceNode subclass: #BlockSequenceNode
  182. instanceVariableNames: ''
  183. category: 'Compiler'!
  184. !BlockSequenceNode methodsFor: 'testing'!
  185. isBlockSequenceNode
  186. ^true
  187. ! !
  188. !BlockSequenceNode methodsFor: 'visiting'!
  189. accept: aVisitor
  190. aVisitor visitBlockSequenceNode: self
  191. ! !
  192. Node subclass: #ReturnNode
  193. instanceVariableNames: ''
  194. category: 'Compiler'!
  195. !ReturnNode methodsFor: 'visiting'!
  196. accept: aVisitor
  197. aVisitor visitReturnNode: self
  198. ! !
  199. Node subclass: #ValueNode
  200. instanceVariableNames: 'value'
  201. category: 'Compiler'!
  202. !ValueNode methodsFor: 'accessing'!
  203. value
  204. ^value
  205. !
  206. value: anObject
  207. value := anObject
  208. ! !
  209. !ValueNode methodsFor: 'testing'!
  210. isValueNode
  211. ^true
  212. ! !
  213. !ValueNode methodsFor: 'visiting'!
  214. accept: aVisitor
  215. aVisitor visitValueNode: self
  216. ! !
  217. ValueNode subclass: #VariableNode
  218. instanceVariableNames: 'assigned'
  219. category: 'Compiler'!
  220. !VariableNode methodsFor: 'accessing'!
  221. assigned
  222. ^assigned ifNil: [false]
  223. !
  224. assigned: aBoolean
  225. assigned := aBoolean
  226. ! !
  227. !VariableNode methodsFor: 'visiting'!
  228. accept: aVisitor
  229. aVisitor visitVariableNode: self
  230. ! !
  231. VariableNode subclass: #ClassReferenceNode
  232. instanceVariableNames: ''
  233. category: 'Compiler'!
  234. !ClassReferenceNode methodsFor: 'visiting'!
  235. accept: aVisitor
  236. aVisitor visitClassReferenceNode: self
  237. ! !
  238. Node subclass: #JSStatementNode
  239. instanceVariableNames: 'source'
  240. category: 'Compiler'!
  241. !JSStatementNode methodsFor: 'accessing'!
  242. source
  243. ^source ifNil: ['']
  244. !
  245. source: aString
  246. source := aString
  247. ! !
  248. !JSStatementNode methodsFor: 'visiting'!
  249. accept: aVisitor
  250. aVisitor visitJSStatementNode: self
  251. ! !
  252. Object subclass: #NodeVisitor
  253. instanceVariableNames: ''
  254. category: 'Compiler'!
  255. !NodeVisitor methodsFor: 'visiting'!
  256. visit: aNode
  257. aNode accept: self
  258. !
  259. visitNode: aNode
  260. !
  261. visitMethodNode: aNode
  262. self visitNode: aNode
  263. !
  264. visitSequenceNode: aNode
  265. self visitNode: aNode
  266. !
  267. visitBlockSequenceNode: aNode
  268. self visitSequenceNode: aNode
  269. !
  270. visitBlockNode: aNode
  271. self visitNode: aNode
  272. !
  273. visitReturnNode: aNode
  274. self visitNode: aNode
  275. !
  276. visitSendNode: aNode
  277. self visitNode: aNode
  278. !
  279. visitCascadeNode: aNode
  280. self visitNode: aNode
  281. !
  282. visitValueNode: aNode
  283. self visitNode: aNode
  284. !
  285. visitVariableNode: aNode
  286. !
  287. visitAssignmentNode: aNode
  288. self visitNode: aNode
  289. !
  290. visitClassReferenceNode: aNode
  291. self
  292. nextPutAll: 'smalltalk.';
  293. nextPutAll: aNode value
  294. !
  295. visitJSStatementNode: aNode
  296. self
  297. nextPutAll: 'function(){';
  298. nextPutAll: aNode source;
  299. nextPutAll: '})()'
  300. ! !
  301. NodeVisitor subclass: #Compiler
  302. instanceVariableNames: 'stream nestedBlocks earlyReturn currentClass currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced source'
  303. category: 'Compiler'!
  304. !Compiler methodsFor: 'accessing'!
  305. parser
  306. ^SmalltalkParser new
  307. !
  308. currentClass
  309. ^currentClass
  310. !
  311. currentClass: aClass
  312. currentClass := aClass
  313. !
  314. unknownVariables
  315. ^unknownVariables copy
  316. !
  317. pseudoVariables
  318. ^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
  319. !
  320. tempVariables
  321. ^tempVariables copy
  322. !
  323. knownVariables
  324. ^self pseudoVariables
  325. addAll: self tempVariables;
  326. yourself
  327. !
  328. classNameFor: aClass
  329. ^aClass isMetaclass
  330. ifTrue: [aClass instanceClass name, '.klass']
  331. ifFalse: [
  332. aClass isNil
  333. ifTrue: ['nil']
  334. ifFalse: [aClass name]]
  335. !
  336. source
  337. ^source ifNil: ['']
  338. !
  339. source: aString
  340. source := aString
  341. ! !
  342. !Compiler methodsFor: 'compiling'!
  343. loadExpression: aString
  344. | result |
  345. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  346. result := DoIt new doIt.
  347. DoIt removeCompiledMethod: (DoIt methodDictionary at: #doIt).
  348. ^result
  349. !
  350. load: aString forClass: aClass
  351. | compiled |
  352. compiled := self eval: (self compile: aString forClass: aClass).
  353. self setupClass: aClass.
  354. ^compiled
  355. !
  356. compile: aString forClass: aClass
  357. self currentClass: aClass.
  358. self source: aString.
  359. ^self compile: aString
  360. !
  361. compileExpression: aString
  362. self currentClass: DoIt.
  363. self source: 'doIt ^[', aString, '] value'.
  364. ^self compileNode: (self parse: self source)
  365. !
  366. eval: aString
  367. <return eval(aString)>
  368. !
  369. compile: aString
  370. ^self compileNode: (self parse: aString)
  371. !
  372. compileNode: aNode
  373. stream := '' writeStream.
  374. self visit: aNode.
  375. ^stream contents
  376. !
  377. parse: aString
  378. ^Smalltalk current parse: aString
  379. !
  380. parseExpression: aString
  381. ^self parse: 'doIt ^[', aString, '] value'
  382. !
  383. recompile: aClass
  384. aClass methodDictionary do: [:each || method |
  385. method := self load: each source forClass: aClass.
  386. method category: each category.
  387. aClass addCompiledMethod: method].
  388. aClass isMetaclass ifFalse: [self recompile: aClass class]
  389. !
  390. recompileAll
  391. Smalltalk current classes do: [:each |
  392. Transcript show: each; cr.
  393. [self recompile: each] valueWithTimeout: 100]
  394. !
  395. setupClass: aClass
  396. <smalltalk.init(aClass)>
  397. ! !
  398. !Compiler methodsFor: 'initialization'!
  399. initialize
  400. super initialize.
  401. stream := '' writeStream.
  402. unknownVariables := #().
  403. tempVariables := #().
  404. messageSends := #().
  405. classReferenced := #()
  406. ! !
  407. !Compiler methodsFor: 'optimizations'!
  408. checkClass: aClassName for: receiver
  409. stream nextPutAll: '(($receiver = ', receiver, ').klass === smalltalk.', aClassName, ') ? '
  410. !
  411. inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
  412. | inlined |
  413. inlined := false.
  414. "-- BlockClosures --"
  415. (aSelector = 'whileTrue:') ifTrue: [
  416. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  417. stream nextPutAll: '(function(){while('.
  418. self visit: anObject.
  419. stream nextPutAll: '()) {'.
  420. self visit: aCollection first.
  421. stream nextPutAll: '()}})()'.
  422. inlined := true]].
  423. (aSelector = 'whileFalse:') ifTrue: [
  424. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  425. stream nextPutAll: '(function(){while(!!'.
  426. self visit: anObject.
  427. stream nextPutAll: '()) {'.
  428. self visit: aCollection first.
  429. stream nextPutAll: '()}})()'.
  430. inlined := true]].
  431. (aSelector = 'whileTrue') ifTrue: [
  432. anObject isBlockNode ifTrue: [
  433. stream nextPutAll: '(function(){while('.
  434. self visit: anObject.
  435. stream nextPutAll: '()) {}})()'.
  436. inlined := true]].
  437. (aSelector = 'whileFalse') ifTrue: [
  438. anObject isBlockNode ifTrue: [
  439. stream nextPutAll: '(function(){while(!!'.
  440. self visit: anObject.
  441. stream nextPutAll: '()) {}})()'.
  442. inlined := true]].
  443. "-- Numbers --"
  444. (aSelector = '+') ifTrue: [
  445. (self isNode: anObject ofClass: Number) ifTrue: [
  446. self visit: anObject.
  447. stream nextPutAll: ' + '.
  448. self visit: aCollection first.
  449. inlined := true]].
  450. (aSelector = '-') ifTrue: [
  451. (self isNode: anObject ofClass: Number) ifTrue: [
  452. self visit: anObject.
  453. stream nextPutAll: ' - '.
  454. self visit: aCollection first.
  455. inlined := true]].
  456. (aSelector = '*') ifTrue: [
  457. (self isNode: anObject ofClass: Number) ifTrue: [
  458. self visit: anObject.
  459. stream nextPutAll: ' * '.
  460. self visit: aCollection first.
  461. inlined := true]].
  462. (aSelector = '/') ifTrue: [
  463. (self isNode: anObject ofClass: Number) ifTrue: [
  464. self visit: anObject.
  465. stream nextPutAll: ' / '.
  466. self visit: aCollection first.
  467. inlined := true]].
  468. (aSelector = '<') ifTrue: [
  469. (self isNode: anObject ofClass: Number) ifTrue: [
  470. self visit: anObject.
  471. stream nextPutAll: ' < '.
  472. self visit: aCollection first.
  473. inlined := true]].
  474. (aSelector = '<=') ifTrue: [
  475. (self isNode: anObject ofClass: Number) ifTrue: [
  476. self visit: anObject.
  477. stream nextPutAll: ' <= '.
  478. self visit: aCollection first.
  479. inlined := true]].
  480. (aSelector = '=') ifTrue: [
  481. (self isNode: anObject ofClass: Number) ifTrue: [
  482. self visit: anObject.
  483. stream nextPutAll: ' == '.
  484. self visit: aCollection first.
  485. inlined := true]].
  486. (aSelector = '>') ifTrue: [
  487. (self isNode: anObject ofClass: Number) ifTrue: [
  488. self visit: anObject.
  489. stream nextPutAll: ' > '.
  490. self visit: aCollection first.
  491. inlined := true]].
  492. (aSelector = '>=') ifTrue: [
  493. (self isNode: anObject ofClass: Number) ifTrue: [
  494. self visit: anObject.
  495. stream nextPutAll: ' >= '.
  496. self visit: aCollection first.
  497. inlined := true]].
  498. "-- UndefinedObject --"
  499. (aSelector = 'ifNil:') ifTrue: [
  500. aCollection first isBlockNode ifTrue: [
  501. stream nextPutAll: '(($receiver = '.
  502. self visit: anObject.
  503. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  504. self visit: aCollection first.
  505. stream nextPutAll: '() : $receiver'.
  506. inlined := true]].
  507. (aSelector = 'ifNotNil:') ifTrue: [
  508. aCollection first isBlockNode ifTrue: [
  509. stream nextPutAll: '(($receiver = '.
  510. self visit: anObject.
  511. stream nextPutAll: ') !!= nil && $receiver !!= undefined) ? '.
  512. self visit: aCollection first.
  513. stream nextPutAll: '() : nil'.
  514. inlined := true]].
  515. (aSelector = 'ifNil:ifNotNil:') ifTrue: [
  516. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  517. stream nextPutAll: '(($receiver = '.
  518. self visit: anObject.
  519. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  520. self visit: aCollection first.
  521. stream nextPutAll: '() : '.
  522. self visit: aCollection second.
  523. stream nextPutAll: '()'.
  524. inlined := true]].
  525. (aSelector = 'ifNotNil:ifNil:') ifTrue: [
  526. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  527. stream nextPutAll: '(($receiver = '.
  528. self visit: anObject.
  529. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  530. self visit: aCollection second.
  531. stream nextPutAll: '() : '.
  532. self visit: aCollection first.
  533. stream nextPutAll: '()'.
  534. inlined := true]].
  535. ^inlined
  536. !
  537. isNode: aNode ofClass: aClass
  538. ^aNode isValueNode and: [
  539. aNode value class = aClass or: [
  540. aNode value = 'self' and: [self currentClass = aClass]]]
  541. !
  542. inline: aSelector receiver: receiver argumentNodes: aCollection
  543. | inlined |
  544. inlined := false.
  545. "-- Booleans --"
  546. (aSelector = 'ifFalse:') ifTrue: [
  547. aCollection first isBlockNode ifTrue: [
  548. self checkClass: 'Boolean' for: receiver.
  549. stream nextPutAll: '(!! $receiver ? '.
  550. self visit: aCollection first.
  551. stream nextPutAll: '() : nil)'.
  552. inlined := true]].
  553. (aSelector = 'ifTrue:') ifTrue: [
  554. aCollection first isBlockNode ifTrue: [
  555. self checkClass: 'Boolean' for: receiver.
  556. stream nextPutAll: '($receiver ? '.
  557. self visit: aCollection first.
  558. stream nextPutAll: '() : nil)'.
  559. inlined := true]].
  560. (aSelector = 'ifTrue:ifFalse:') ifTrue: [
  561. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  562. self checkClass: 'Boolean' for: receiver.
  563. stream nextPutAll: '($receiver ? '.
  564. self visit: aCollection first.
  565. stream nextPutAll: '() : '.
  566. self visit: aCollection second.
  567. stream nextPutAll: '())'.
  568. inlined := true]].
  569. (aSelector = 'ifFalse:ifTrue:') ifTrue: [
  570. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  571. self checkClass: 'Boolean' for: receiver.
  572. stream nextPutAll: '(!! $receiver ? '.
  573. self visit: aCollection first.
  574. stream nextPutAll: '() : '.
  575. self visit: aCollection second.
  576. stream nextPutAll: '())'.
  577. inlined := true]].
  578. "-- Numbers --"
  579. (aSelector = '<') ifTrue: [
  580. self checkClass: 'Number' for: receiver.
  581. stream nextPutAll: '$receiver <'.
  582. self visit: aCollection first.
  583. inlined := true].
  584. (aSelector = '<=') ifTrue: [
  585. self checkClass: 'Number' for: receiver.
  586. stream nextPutAll: '$receiver <='.
  587. self visit: aCollection first.
  588. inlined := true].
  589. (aSelector = '>') ifTrue: [
  590. self checkClass: 'Number' for: receiver.
  591. stream nextPutAll: '$receiver >'.
  592. self visit: aCollection first.
  593. inlined := true].
  594. (aSelector = '>=') ifTrue: [
  595. self checkClass: 'Number' for: receiver.
  596. stream nextPutAll: '$receiver >='.
  597. self visit: aCollection first.
  598. inlined := true].
  599. (aSelector = '+') ifTrue: [
  600. self checkClass: 'Number' for: receiver.
  601. stream nextPutAll: '$receiver +'.
  602. self visit: aCollection first.
  603. inlined := true].
  604. (aSelector = '-') ifTrue: [
  605. self checkClass: 'Number' for: receiver.
  606. stream nextPutAll: '$receiver -'.
  607. self visit: aCollection first.
  608. inlined := true].
  609. (aSelector = '*') ifTrue: [
  610. self checkClass: 'Number' for: receiver.
  611. stream nextPutAll: '$receiver *'.
  612. self visit: aCollection first.
  613. inlined := true].
  614. (aSelector = '/') ifTrue: [
  615. self checkClass: 'Number' for: receiver.
  616. stream nextPutAll: '$receiver /'.
  617. self visit: aCollection first.
  618. inlined := true].
  619. ^inlined
  620. ! !
  621. !Compiler methodsFor: 'testing'!
  622. performOptimizations
  623. ^self class performOptimizations
  624. ! !
  625. !Compiler methodsFor: 'visiting'!
  626. visit: aNode
  627. aNode accept: self
  628. !
  629. visitMethodNode: aNode
  630. | str currentSelector |
  631. currentSelector := aNode selector asSelector.
  632. nestedBlocks := 0.
  633. earlyReturn := false.
  634. messageSends := #().
  635. referencedClasses := #().
  636. unknownVariables := #().
  637. tempVariables := #().
  638. stream
  639. nextPutAll: 'smalltalk.method({'; lf;
  640. nextPutAll: 'selector: "', aNode selector, '",'; lf.
  641. stream nextPutAll: 'source: unescape("', self source escaped, '"),';lf.
  642. stream nextPutAll: 'fn: function('.
  643. aNode arguments
  644. do: [:each |
  645. tempVariables add: each.
  646. stream nextPutAll: each]
  647. separatedBy: [stream nextPutAll: ', '].
  648. stream
  649. nextPutAll: '){'; lf;
  650. nextPutAll: 'var self=this;'; lf.
  651. str := stream.
  652. stream := '' writeStream.
  653. aNode nodes do: [:each |
  654. self visit: each].
  655. earlyReturn ifTrue: [
  656. str nextPutAll: 'try{'].
  657. str nextPutAll: stream contents.
  658. stream := str.
  659. stream
  660. lf;
  661. nextPutAll: 'return self;'.
  662. earlyReturn ifTrue: [
  663. stream lf; nextPutAll: '} catch(e) {if(e.name === ''stReturn'' && e.selector === ', currentSelector printString, '){return e.fn()} throw(e)}'].
  664. stream nextPutAll: '}'.
  665. stream
  666. nextPutAll: ',', String lf, 'messageSends: ';
  667. nextPutAll: messageSends asJavascript, ','; lf;
  668. nextPutAll: 'referencedClasses: ['.
  669. referencedClasses
  670. do: [:each | stream nextPutAll: each]
  671. separatedBy: [stream nextPutAll: ','].
  672. stream nextPutAll: ']'.
  673. stream nextPutAll: '})'
  674. !
  675. visitBlockNode: aNode
  676. stream nextPutAll: '(function('.
  677. aNode parameters
  678. do: [:each |
  679. tempVariables add: each.
  680. stream nextPutAll: each]
  681. separatedBy: [stream nextPutAll: ', '].
  682. stream nextPutAll: '){'.
  683. aNode nodes do: [:each | self visit: each].
  684. stream nextPutAll: '})'
  685. !
  686. visitSequenceNode: aNode
  687. aNode temps do: [:each |
  688. tempVariables add: each.
  689. stream nextPutAll: 'var ', each, '=nil;'; lf].
  690. aNode nodes do: [:each |
  691. self visit: each.
  692. stream nextPutAll: ';']
  693. separatedBy: [stream lf]
  694. !
  695. visitBlockSequenceNode: aNode
  696. | index |
  697. nestedBlocks := nestedBlocks + 1.
  698. aNode nodes isEmpty
  699. ifTrue: [
  700. stream nextPutAll: 'return nil;']
  701. ifFalse: [
  702. aNode temps do: [:each |
  703. tempVariables add: each.
  704. stream nextPutAll: 'var ', each, '=nil;'; lf].
  705. index := 0.
  706. aNode nodes do: [:each |
  707. index := index + 1.
  708. index = aNode nodes size ifTrue: [
  709. stream nextPutAll: 'return '].
  710. self visit: each.
  711. stream nextPutAll: ';']].
  712. nestedBlocks := nestedBlocks - 1
  713. !
  714. visitReturnNode: aNode
  715. nestedBlocks > 0 ifTrue: [
  716. earlyReturn := true].
  717. earlyReturn
  718. ifTrue: [
  719. stream
  720. nextPutAll: '(function(){throw(';
  721. nextPutAll: '{name: ''stReturn'', selector: ';
  722. nextPutAll: currentSelector printString;
  723. nextPutAll: ', fn: function(){return ']
  724. ifFalse: [stream nextPutAll: 'return '].
  725. aNode nodes do: [:each |
  726. self visit: each].
  727. earlyReturn ifTrue: [
  728. stream nextPutAll: '}})})()']
  729. !
  730. visitSendNode: aNode
  731. | str receiver superSend inlined |
  732. str := stream.
  733. (messageSends includes: aNode selector) ifFalse: [
  734. messageSends add: aNode selector].
  735. stream := '' writeStream.
  736. self visit: aNode receiver.
  737. superSend := stream contents = 'super'.
  738. receiver := superSend ifTrue: ['self'] ifFalse: [stream contents].
  739. stream := str.
  740. self performOptimizations
  741. ifTrue: [
  742. (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifFalse: [
  743. (self inline: aNode selector receiver: receiver argumentNodes: aNode arguments)
  744. ifTrue: [stream nextPutAll: ' : ', (self send: aNode selector to: '$receiver' arguments: aNode arguments superSend: superSend)]
  745. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]]]
  746. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]
  747. !
  748. visitCascadeNode: aNode
  749. | index |
  750. index := 0.
  751. (tempVariables includes: '$rec') ifFalse: [
  752. tempVariables add: '$rec'].
  753. stream nextPutAll: '(function($rec){'.
  754. aNode nodes do: [:each |
  755. index := index + 1.
  756. index = aNode nodes size ifTrue: [
  757. stream nextPutAll: 'return '].
  758. each receiver: (VariableNode new value: '$rec').
  759. self visit: each.
  760. stream nextPutAll: ';'].
  761. stream nextPutAll: '})('.
  762. self visit: aNode receiver.
  763. stream nextPutAll: ')'
  764. !
  765. visitValueNode: aNode
  766. stream nextPutAll: aNode value asJavascript
  767. !
  768. visitAssignmentNode: aNode
  769. self visit: aNode left.
  770. stream nextPutAll: '='.
  771. self visit: aNode right
  772. !
  773. visitClassReferenceNode: aNode
  774. | klass |
  775. klass := '(smalltalk.', aNode value, ' || ', aNode value, ')'.
  776. (Smalltalk current at: aNode value) isClass ifTrue: [
  777. (referencedClasses includes: klass)
  778. ifFalse: [referencedClasses add: klass]].
  779. stream nextPutAll: klass
  780. !
  781. visitVariableNode: aNode
  782. (self currentClass allInstanceVariableNames includes: aNode value)
  783. ifTrue: [stream nextPutAll: 'self[''@', aNode value, ''']']
  784. ifFalse: [
  785. (self knownVariables includes: aNode value)
  786. ifFalse: [
  787. unknownVariables add: aNode value.
  788. aNode assigned
  789. ifTrue: [stream nextPutAll: aNode value]
  790. ifFalse: [stream nextPutAll: '(typeof ', aNode value, ' == ''undefined'' ? nil : ', aNode value, ')']]
  791. ifTrue: [
  792. stream nextPutAll:aNode value]]
  793. !
  794. visitJSStatementNode: aNode
  795. stream nextPutAll: (aNode source replace: '>>' with: '>')
  796. !
  797. visitFailure: aFailure
  798. self error: aFailure asString
  799. !
  800. send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
  801. ^String streamContents: [:str || tmp |
  802. tmp := stream.
  803. str nextPutAll: 'smalltalk.send('.
  804. str nextPutAll: aReceiver.
  805. str nextPutAll: ', "', aSelector asSelector, '", ['.
  806. stream := str.
  807. aCollection
  808. do: [:each | self visit: each]
  809. separatedBy: [stream nextPutAll: ', '].
  810. stream := tmp.
  811. str nextPutAll: ']'.
  812. aBoolean ifTrue: [
  813. str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass superclass)].
  814. str nextPutAll: ')']
  815. ! !
  816. Compiler class instanceVariableNames: 'performOptimizations'!
  817. !Compiler class methodsFor: 'accessing'!
  818. performOptimizations
  819. ^performOptimizations ifNil: [true]
  820. !
  821. performOptimizations: aBoolean
  822. performOptimizations := aBoolean
  823. ! !
  824. !Compiler class methodsFor: 'compiling'!
  825. recompile: aClass
  826. aClass methodDictionary do: [:each || method |
  827. method := self new load: each source forClass: aClass.
  828. method category: each category.
  829. aClass addCompiledMethod: method].
  830. aClass isMetaclass ifFalse: [self recompile: aClass class]
  831. !
  832. recompileAll
  833. Smalltalk current classes do: [:each |
  834. self recompile: each]
  835. ! !
  836. Object subclass: #DoIt
  837. instanceVariableNames: ''
  838. category: 'Compiler'!
  839. !DoIt methodsFor: ''!
  840. ! !