Compiler.st 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  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'
  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. !Compiler methodsFor: 'compiling'!
  337. loadExpression: aString
  338. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  339. ^DoIt new doIt
  340. !
  341. load: aString forClass: aClass
  342. | compiled |
  343. compiled := self eval: (self compile: aString forClass: aClass).
  344. self setupClass: aClass.
  345. ^compiled
  346. !
  347. compile: aString forClass: aClass
  348. self currentClass: aClass.
  349. ^self compile: aString
  350. !
  351. compileExpression: aString
  352. self currentClass: DoIt.
  353. ^self compileNode: (self parseExpression: aString)
  354. !
  355. eval: aString
  356. <return eval(aString)>
  357. !
  358. compile: aString
  359. ^self compileNode: (self parse: aString)
  360. !
  361. compileNode: aNode
  362. stream := '' writeStream.
  363. self visit: aNode.
  364. ^stream contents
  365. !
  366. parse: aString
  367. ^self parser parse: aString readStream
  368. !
  369. parseExpression: aString
  370. ^self parse: 'doIt ^[', aString, '] value'
  371. !
  372. recompile: aClass
  373. aClass methodDictionary do: [:each || method |
  374. method := self load: each source forClass: aClass.
  375. method category: each category.
  376. aClass addCompiledMethod: method].
  377. aClass isMetaclass ifFalse: [self recompile: aClass class]
  378. !
  379. recompileAll
  380. Smalltalk current classes do: [:each |
  381. Transcript show: each; cr.
  382. [self recompile: each] valueWithTimeout: 100]
  383. !
  384. setupClass: aClass
  385. <smalltalk.init(aClass)>
  386. ! !
  387. !Compiler methodsFor: 'initialization'!
  388. initialize
  389. super initialize.
  390. stream := '' writeStream.
  391. unknownVariables := #().
  392. tempVariables := #().
  393. messageSends := #().
  394. classReferenced := #()
  395. ! !
  396. !Compiler methodsFor: 'optimizations'!
  397. checkClass: aClassName for: receiver
  398. stream nextPutAll: '(($receiver = ', receiver, ').klass === smalltalk.', aClassName, ') ? '
  399. !
  400. inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
  401. | inlined |
  402. inlined := false.
  403. "-- BlockClosures --"
  404. (aSelector = 'whileTrue:') ifTrue: [
  405. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  406. stream nextPutAll: '(function(){while('.
  407. self visit: anObject.
  408. stream nextPutAll: '()) {'.
  409. self visit: aCollection first.
  410. stream nextPutAll: '()}})()'.
  411. inlined := true]].
  412. (aSelector = 'whileFalse:') ifTrue: [
  413. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  414. stream nextPutAll: '(function(){while(!!'.
  415. self visit: anObject.
  416. stream nextPutAll: '()) {'.
  417. self visit: aCollection first.
  418. stream nextPutAll: '()}})()'.
  419. inlined := true]].
  420. (aSelector = 'whileTrue') ifTrue: [
  421. anObject isBlockNode ifTrue: [
  422. stream nextPutAll: '(function(){while('.
  423. self visit: anObject.
  424. stream nextPutAll: '()) {}})()'.
  425. inlined := true]].
  426. (aSelector = 'whileFalse') ifTrue: [
  427. anObject isBlockNode ifTrue: [
  428. stream nextPutAll: '(function(){while(!!'.
  429. self visit: anObject.
  430. stream nextPutAll: '()) {}})()'.
  431. inlined := true]].
  432. "-- Numbers --"
  433. (aSelector = '+') ifTrue: [
  434. (self isNode: anObject ofClass: Number) ifTrue: [
  435. self visit: anObject.
  436. stream nextPutAll: ' + '.
  437. self visit: aCollection first.
  438. inlined := true]].
  439. (aSelector = '-') ifTrue: [
  440. (self isNode: anObject ofClass: Number) ifTrue: [
  441. self visit: anObject.
  442. stream nextPutAll: ' - '.
  443. self visit: aCollection first.
  444. inlined := true]].
  445. (aSelector = '*') ifTrue: [
  446. (self isNode: anObject ofClass: Number) ifTrue: [
  447. self visit: anObject.
  448. stream nextPutAll: ' * '.
  449. self visit: aCollection first.
  450. inlined := true]].
  451. (aSelector = '/') ifTrue: [
  452. (self isNode: anObject ofClass: Number) ifTrue: [
  453. self visit: anObject.
  454. stream nextPutAll: ' / '.
  455. self visit: aCollection first.
  456. inlined := true]].
  457. (aSelector = '<') ifTrue: [
  458. (self isNode: anObject ofClass: Number) ifTrue: [
  459. self visit: anObject.
  460. stream nextPutAll: ' < '.
  461. self visit: aCollection first.
  462. inlined := true]].
  463. (aSelector = '<=') ifTrue: [
  464. (self isNode: anObject ofClass: Number) ifTrue: [
  465. self visit: anObject.
  466. stream nextPutAll: ' <= '.
  467. self visit: aCollection first.
  468. inlined := true]].
  469. (aSelector = '=') ifTrue: [
  470. (self isNode: anObject ofClass: Number) ifTrue: [
  471. self visit: anObject.
  472. stream nextPutAll: ' == '.
  473. self visit: aCollection first.
  474. inlined := true]].
  475. (aSelector = '>') ifTrue: [
  476. (self isNode: anObject ofClass: Number) ifTrue: [
  477. self visit: anObject.
  478. stream nextPutAll: ' > '.
  479. self visit: aCollection first.
  480. inlined := true]].
  481. (aSelector = '>=') ifTrue: [
  482. (self isNode: anObject ofClass: Number) ifTrue: [
  483. self visit: anObject.
  484. stream nextPutAll: ' >= '.
  485. self visit: aCollection first.
  486. inlined := true]].
  487. "-- UndefinedObject --"
  488. (aSelector = 'ifNil:') ifTrue: [
  489. aCollection first isBlockNode ifTrue: [
  490. stream nextPutAll: '(($receiver = '.
  491. self visit: anObject.
  492. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  493. self visit: aCollection first.
  494. stream nextPutAll: '() : $receiver'.
  495. inlined := true]].
  496. (aSelector = 'ifNotNil:') ifTrue: [
  497. aCollection first isBlockNode ifTrue: [
  498. stream nextPutAll: '(($receiver = '.
  499. self visit: anObject.
  500. stream nextPutAll: ') !!= nil && $receiver !!= undefined) ? '.
  501. self visit: aCollection first.
  502. stream nextPutAll: '() : nil'.
  503. inlined := true]].
  504. (aSelector = 'ifNil:ifNotNil:') ifTrue: [
  505. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  506. stream nextPutAll: '(($receiver = '.
  507. self visit: anObject.
  508. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  509. self visit: aCollection first.
  510. stream nextPutAll: '() : '.
  511. self visit: aCollection second.
  512. stream nextPutAll: '()'.
  513. inlined := true]].
  514. (aSelector = 'ifNotNil:ifNil:') ifTrue: [
  515. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  516. stream nextPutAll: '(($receiver = '.
  517. self visit: anObject.
  518. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  519. self visit: aCollection second.
  520. stream nextPutAll: '() : '.
  521. self visit: aCollection first.
  522. stream nextPutAll: '()'.
  523. inlined := true]].
  524. ^inlined
  525. !
  526. isNode: aNode ofClass: aClass
  527. ^aNode isValueNode and: [
  528. aNode value class = aClass or: [
  529. aNode value = 'self' and: [self currentClass = aClass]]]
  530. !
  531. inline: aSelector receiver: receiver argumentNodes: aCollection
  532. | inlined |
  533. inlined := false.
  534. "-- Booleans --"
  535. (aSelector = 'ifFalse:') ifTrue: [
  536. aCollection first isBlockNode ifTrue: [
  537. self checkClass: 'Boolean' for: receiver.
  538. stream nextPutAll: '(!! $receiver ? '.
  539. self visit: aCollection first.
  540. stream nextPutAll: '() : nil)'.
  541. inlined := true]].
  542. (aSelector = 'ifTrue:') ifTrue: [
  543. aCollection first isBlockNode ifTrue: [
  544. self checkClass: 'Boolean' for: receiver.
  545. stream nextPutAll: '($receiver ? '.
  546. self visit: aCollection first.
  547. stream nextPutAll: '() : nil)'.
  548. inlined := true]].
  549. (aSelector = 'ifTrue:ifFalse:') ifTrue: [
  550. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  551. self checkClass: 'Boolean' for: receiver.
  552. stream nextPutAll: '($receiver ? '.
  553. self visit: aCollection first.
  554. stream nextPutAll: '() : '.
  555. self visit: aCollection second.
  556. stream nextPutAll: '())'.
  557. inlined := true]].
  558. (aSelector = 'ifFalse:ifTrue:') ifTrue: [
  559. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  560. self checkClass: 'Boolean' for: receiver.
  561. stream nextPutAll: '(!! $receiver ? '.
  562. self visit: aCollection first.
  563. stream nextPutAll: '() : '.
  564. self visit: aCollection second.
  565. stream nextPutAll: '())'.
  566. inlined := true]].
  567. "-- Numbers --"
  568. (aSelector = '<') ifTrue: [
  569. self checkClass: 'Number' for: receiver.
  570. stream nextPutAll: '$receiver <'.
  571. self visit: aCollection first.
  572. inlined := true].
  573. (aSelector = '<=') ifTrue: [
  574. self checkClass: 'Number' for: receiver.
  575. stream nextPutAll: '$receiver <='.
  576. self visit: aCollection first.
  577. inlined := true].
  578. (aSelector = '>') ifTrue: [
  579. self checkClass: 'Number' for: receiver.
  580. stream nextPutAll: '$receiver >'.
  581. self visit: aCollection first.
  582. inlined := true].
  583. (aSelector = '>=') ifTrue: [
  584. self checkClass: 'Number' for: receiver.
  585. stream nextPutAll: '$receiver >='.
  586. self visit: aCollection first.
  587. inlined := true].
  588. (aSelector = '+') ifTrue: [
  589. self checkClass: 'Number' for: receiver.
  590. stream nextPutAll: '$receiver +'.
  591. self visit: aCollection first.
  592. inlined := true].
  593. (aSelector = '-') ifTrue: [
  594. self checkClass: 'Number' for: receiver.
  595. stream nextPutAll: '$receiver -'.
  596. self visit: aCollection first.
  597. inlined := true].
  598. (aSelector = '*') ifTrue: [
  599. self checkClass: 'Number' for: receiver.
  600. stream nextPutAll: '$receiver *'.
  601. self visit: aCollection first.
  602. inlined := true].
  603. (aSelector = '/') ifTrue: [
  604. self checkClass: 'Number' for: receiver.
  605. stream nextPutAll: '$receiver /'.
  606. self visit: aCollection first.
  607. inlined := true].
  608. ^inlined
  609. ! !
  610. !Compiler methodsFor: 'testing'!
  611. performOptimizations
  612. ^self class performOptimizations
  613. ! !
  614. !Compiler methodsFor: 'visiting'!
  615. visit: aNode
  616. aNode accept: self
  617. !
  618. visitMethodNode: aNode
  619. | str currentSelector |
  620. currentSelector := aNode selector asSelector.
  621. nestedBlocks := 0.
  622. earlyReturn := false.
  623. messageSends := #().
  624. referencedClasses := #().
  625. unknownVariables := #().
  626. tempVariables := #().
  627. stream
  628. nextPutAll: 'smalltalk.method({'; lf;
  629. nextPutAll: 'selector: "', aNode selector, '",'; lf.
  630. stream nextPutAll: 'source: unescape("', aNode source escaped, '"),';lf.
  631. stream nextPutAll: 'fn: function('.
  632. aNode arguments
  633. do: [:each |
  634. tempVariables add: each.
  635. stream nextPutAll: each]
  636. separatedBy: [stream nextPutAll: ', '].
  637. stream
  638. nextPutAll: '){'; lf;
  639. nextPutAll: 'var self=this;'; lf.
  640. str := stream.
  641. stream := '' writeStream.
  642. aNode nodes do: [:each |
  643. self visit: each].
  644. earlyReturn ifTrue: [
  645. str nextPutAll: 'try{'].
  646. str nextPutAll: stream contents.
  647. stream := str.
  648. stream
  649. lf;
  650. nextPutAll: 'return self;'.
  651. earlyReturn ifTrue: [
  652. stream lf; nextPutAll: '} catch(e) {if(e.name === ''stReturn'' && e.selector === ', currentSelector printString, '){return e.fn()} throw(e)}'].
  653. stream nextPutAll: '}'.
  654. stream
  655. nextPutAll: ',', String lf, 'messageSends: ';
  656. nextPutAll: messageSends asJavascript, ','; lf;
  657. nextPutAll: 'referencedClasses: ['.
  658. referencedClasses
  659. do: [:each | stream nextPutAll: each]
  660. separatedBy: [stream nextPutAll: ','].
  661. stream nextPutAll: ']'.
  662. stream nextPutAll: '})'
  663. !
  664. visitBlockNode: aNode
  665. stream nextPutAll: '(function('.
  666. aNode parameters
  667. do: [:each |
  668. tempVariables add: each.
  669. stream nextPutAll: each]
  670. separatedBy: [stream nextPutAll: ', '].
  671. stream nextPutAll: '){'.
  672. aNode nodes do: [:each | self visit: each].
  673. stream nextPutAll: '})'
  674. !
  675. visitSequenceNode: aNode
  676. aNode temps do: [:each |
  677. tempVariables add: each.
  678. stream nextPutAll: 'var ', each, '=nil;'; lf].
  679. aNode nodes do: [:each |
  680. self visit: each.
  681. stream nextPutAll: ';']
  682. separatedBy: [stream lf]
  683. !
  684. visitBlockSequenceNode: aNode
  685. | index |
  686. nestedBlocks := nestedBlocks + 1.
  687. aNode nodes isEmpty
  688. ifTrue: [
  689. stream nextPutAll: 'return nil;']
  690. ifFalse: [
  691. aNode temps do: [:each |
  692. tempVariables add: each.
  693. stream nextPutAll: 'var ', each, '=nil;'; lf].
  694. index := 0.
  695. aNode nodes do: [:each |
  696. index := index + 1.
  697. index = aNode nodes size ifTrue: [
  698. stream nextPutAll: 'return '].
  699. self visit: each.
  700. stream nextPutAll: ';']].
  701. nestedBlocks := nestedBlocks - 1
  702. !
  703. visitReturnNode: aNode
  704. nestedBlocks > 0 ifTrue: [
  705. earlyReturn := true].
  706. earlyReturn
  707. ifTrue: [
  708. stream
  709. nextPutAll: '(function(){throw(';
  710. nextPutAll: '{name: ''stReturn'', selector: ';
  711. nextPutAll: currentSelector printString;
  712. nextPutAll: ', fn: function(){return ']
  713. ifFalse: [stream nextPutAll: 'return '].
  714. aNode nodes do: [:each |
  715. self visit: each].
  716. earlyReturn ifTrue: [
  717. stream nextPutAll: '}})})()']
  718. !
  719. visitSendNode: aNode
  720. | str receiver superSend inlined |
  721. str := stream.
  722. (messageSends includes: aNode selector) ifFalse: [
  723. messageSends add: aNode selector].
  724. stream := '' writeStream.
  725. self visit: aNode receiver.
  726. superSend := stream contents = 'super'.
  727. receiver := superSend ifTrue: ['self'] ifFalse: [stream contents].
  728. stream := str.
  729. self performOptimizations
  730. ifTrue: [
  731. (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifFalse: [
  732. (self inline: aNode selector receiver: receiver argumentNodes: aNode arguments)
  733. ifTrue: [stream nextPutAll: ' : ', (self send: aNode selector to: '$receiver' arguments: aNode arguments superSend: superSend)]
  734. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]]]
  735. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]
  736. !
  737. visitCascadeNode: aNode
  738. | index |
  739. index := 0.
  740. (tempVariables includes: '$rec') ifFalse: [
  741. tempVariables add: '$rec'].
  742. stream nextPutAll: '(function($rec){'.
  743. aNode nodes do: [:each |
  744. index := index + 1.
  745. index = aNode nodes size ifTrue: [
  746. stream nextPutAll: 'return '].
  747. each receiver: (VariableNode new value: '$rec').
  748. self visit: each.
  749. stream nextPutAll: ';'].
  750. stream nextPutAll: '})('.
  751. self visit: aNode receiver.
  752. stream nextPutAll: ')'
  753. !
  754. visitValueNode: aNode
  755. stream nextPutAll: aNode value asJavascript
  756. !
  757. visitAssignmentNode: aNode
  758. self visit: aNode left.
  759. stream nextPutAll: '='.
  760. self visit: aNode right
  761. !
  762. visitClassReferenceNode: aNode
  763. | klass |
  764. klass := '(smalltalk.', aNode value, ' || ', aNode value, ')'.
  765. (Smalltalk current at: aNode value) isClass ifTrue: [
  766. (referencedClasses includes: klass)
  767. ifFalse: [referencedClasses add: klass]].
  768. stream nextPutAll: klass
  769. !
  770. visitVariableNode: aNode
  771. (self currentClass allInstanceVariableNames includes: aNode value)
  772. ifTrue: [stream nextPutAll: 'self[''@', aNode value, ''']']
  773. ifFalse: [
  774. (self knownVariables includes: aNode value)
  775. ifFalse: [
  776. unknownVariables add: aNode value.
  777. aNode assigned
  778. ifTrue: [stream nextPutAll: aNode value]
  779. ifFalse: [stream nextPutAll: '(typeof ', aNode value, ' == ''undefined'' ? nil : ', aNode value, ')']]
  780. ifTrue: [
  781. stream nextPutAll:aNode value]]
  782. !
  783. visitJSStatementNode: aNode
  784. stream nextPutAll: (aNode source replace: '>>' with: '>')
  785. !
  786. visitFailure: aFailure
  787. self error: aFailure asString
  788. !
  789. send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
  790. ^String streamContents: [:str || tmp |
  791. tmp := stream.
  792. str nextPutAll: 'smalltalk.send('.
  793. str nextPutAll: aReceiver.
  794. str nextPutAll: ', "', aSelector asSelector, '", ['.
  795. stream := str.
  796. aCollection
  797. do: [:each | self visit: each]
  798. separatedBy: [stream nextPutAll: ', '].
  799. stream := tmp.
  800. str nextPutAll: ']'.
  801. aBoolean ifTrue: [
  802. str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass superclass)].
  803. str nextPutAll: ')']
  804. ! !
  805. Compiler class instanceVariableNames: 'performOptimizations'!
  806. !Compiler class methodsFor: 'accessing'!
  807. performOptimizations
  808. ^performOptimizations ifNil: [true]
  809. !
  810. performOptimizations: aBoolean
  811. performOptimizations := aBoolean
  812. ! !
  813. !Compiler class methodsFor: 'compiling'!
  814. recompile: aClass
  815. aClass methodDictionary do: [:each || method |
  816. method := self new load: each source forClass: aClass.
  817. method category: each category.
  818. aClass addCompiledMethod: method].
  819. aClass isMetaclass ifFalse: [self recompile: aClass class]
  820. !
  821. recompileAll
  822. Smalltalk current classes do: [:each |
  823. self recompile: each]
  824. ! !
  825. Object subclass: #DoIt
  826. instanceVariableNames: ''
  827. category: 'Compiler'!
  828. !DoIt methodsFor: ''!
  829. doIt ^[a < 3] value
  830. ! !