Compiler.st 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. Smalltalk current createPackage: 'Compiler' properties: #{}!
  2. Object subclass: #ChunkParser
  3. instanceVariableNames: 'stream'
  4. package: 'Compiler'!
  5. !ChunkParser methodsFor: 'accessing'!
  6. stream: aStream
  7. stream := aStream
  8. ! !
  9. !ChunkParser methodsFor: 'reading'!
  10. nextChunk
  11. "The chunk format (Smalltalk Interchange Format or Fileout format)
  12. is a trivial format but can be a bit tricky to understand:
  13. - Uses the exclamation mark as delimiter of chunks.
  14. - Inside a chunk a normal exclamation mark must be doubled.
  15. - A non empty chunk must be a valid Smalltalk expression.
  16. - A chunk on top level with a preceding empty chunk is an instruction chunk:
  17. - The object created by the expression then takes over reading chunks.
  18. This metod returns next chunk as a String (trimmed), empty String (all whitespace) or nil."
  19. | char result chunk |
  20. result := '' writeStream.
  21. [char := stream next.
  22. char notNil] whileTrue: [
  23. char = '!!' ifTrue: [
  24. stream peek = '!!'
  25. ifTrue: [stream next "skipping the escape double"]
  26. ifFalse: [^result contents trimBoth "chunk end marker found"]].
  27. result nextPut: char].
  28. ^nil "a chunk needs to end with !!"
  29. ! !
  30. !ChunkParser class methodsFor: 'not yet classified'!
  31. on: aStream
  32. ^self new stream: aStream
  33. ! !
  34. Object subclass: #DoIt
  35. instanceVariableNames: ''
  36. package: 'Compiler'!
  37. Object subclass: #Exporter
  38. instanceVariableNames: ''
  39. package: 'Compiler'!
  40. !Exporter methodsFor: 'fileOut'!
  41. exportAll
  42. "Export all packages in the system."
  43. ^String streamContents: [:stream |
  44. Smalltalk current packages do: [:pkg |
  45. stream nextPutAll: (self exportPackage: pkg name)]]
  46. !
  47. exportClass: aClass
  48. "Export a single class. Subclasses override these methods."
  49. ^String streamContents: [:stream |
  50. self exportDefinitionOf: aClass on: stream.
  51. self exportMethodsOf: aClass on: stream.
  52. self exportMetaDefinitionOf: aClass on: stream.
  53. self exportMethodsOf: aClass class on: stream]
  54. !
  55. exportPackage: packageName
  56. "Export a given package by name."
  57. | package |
  58. ^String streamContents: [:stream |
  59. package := Smalltalk current packageAt: packageName.
  60. self exportPackageDefinitionOf: package on: stream.
  61. "Export classes in dependency order"
  62. package sortedClasses do: [:each |
  63. stream nextPutAll: (self exportClass: each)].
  64. self exportPackageExtensionsOf: package on: stream]
  65. ! !
  66. !Exporter methodsFor: 'private'!
  67. classNameFor: aClass
  68. ^aClass isMetaclass
  69. ifTrue: [aClass instanceClass name, '.klass']
  70. ifFalse: [
  71. aClass isNil
  72. ifTrue: ['nil']
  73. ifFalse: [aClass name]]
  74. !
  75. exportDefinitionOf: aClass on: aStream
  76. aStream
  77. nextPutAll: 'smalltalk.addClass(';
  78. nextPutAll: '''', (self classNameFor: aClass), ''', ';
  79. nextPutAll: 'smalltalk.', (self classNameFor: aClass superclass);
  80. nextPutAll: ', ['.
  81. aClass instanceVariableNames
  82. do: [:each | aStream nextPutAll: '''', each, '''']
  83. separatedBy: [aStream nextPutAll: ', '].
  84. aStream
  85. nextPutAll: '], ''';
  86. nextPutAll: aClass category, '''';
  87. nextPutAll: ');'.
  88. aClass comment notEmpty ifTrue: [
  89. aStream
  90. lf;
  91. nextPutAll: 'smalltalk.';
  92. nextPutAll: (self classNameFor: aClass);
  93. nextPutAll: '.comment=';
  94. nextPutAll: 'unescape(''', aClass comment escaped, ''')'].
  95. aStream lf
  96. !
  97. exportMetaDefinitionOf: aClass on: aStream
  98. aClass class instanceVariableNames isEmpty ifFalse: [
  99. aStream
  100. nextPutAll: 'smalltalk.', (self classNameFor: aClass class);
  101. nextPutAll: '.iVarNames = ['.
  102. aClass class instanceVariableNames
  103. do: [:each | aStream nextPutAll: '''', each, '''']
  104. separatedBy: [aStream nextPutAll: ','].
  105. aStream nextPutAll: '];', String lf]
  106. !
  107. exportMethod: aMethod of: aClass on: aStream
  108. aStream
  109. nextPutAll: 'smalltalk.addMethod(';lf;
  110. nextPutAll: 'unescape(''', aMethod selector asSelector escaped, '''),';lf;
  111. nextPutAll: 'smalltalk.method({';lf;
  112. nextPutAll: 'selector: unescape(''', aMethod selector escaped, '''),';lf;
  113. nextPutAll: 'category: ''', aMethod category, ''',';lf;
  114. nextPutAll: 'fn: ', aMethod fn compiledSource, ',';lf;
  115. nextPutAll: 'args: ', aMethod arguments asJavascript, ','; lf;
  116. nextPutAll: 'source: unescape(''', aMethod source escaped, '''),';lf;
  117. nextPutAll: 'messageSends: ', aMethod messageSends asJavascript, ',';lf;
  118. nextPutAll: 'referencedClasses: ', aMethod referencedClasses asJavascript.
  119. aStream
  120. lf;
  121. nextPutAll: '}),';lf;
  122. nextPutAll: 'smalltalk.', (self classNameFor: aClass);
  123. nextPutAll: ');';lf;lf
  124. !
  125. exportMethodsOf: aClass on: aStream
  126. "Issue #143: sort methods alphabetically"
  127. ((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector]) do: [:each |
  128. (each category match: '^\*') ifFalse: [
  129. self exportMethod: each of: aClass on: aStream]].
  130. aStream lf
  131. !
  132. exportPackageDefinitionOf: package on: aStream
  133. aStream
  134. nextPutAll: 'smalltalk.addPackage(';
  135. nextPutAll: '''', package name, ''', ', package propertiesAsJSON , ');'.
  136. aStream lf
  137. !
  138. exportPackageExtensionsOf: package on: aStream
  139. "Issue #143: sort classes and methods alphabetically"
  140. | name |
  141. name := package name.
  142. (Package sortedClasses: Smalltalk current classes) do: [:each |
  143. {each. each class} do: [:aClass |
  144. ((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector]) do: [:method |
  145. (method category match: '^\*', name) ifTrue: [
  146. self exportMethod: method of: aClass on: aStream ]]]]
  147. ! !
  148. Exporter subclass: #ChunkExporter
  149. instanceVariableNames: ''
  150. package: 'Compiler'!
  151. !ChunkExporter methodsFor: 'not yet classified'!
  152. chunkEscape: aString
  153. "Replace all occurrences of !! with !!!! and trim at both ends."
  154. ^(aString replace: '!!' with: '!!!!') trimBoth
  155. !
  156. classNameFor: aClass
  157. ^aClass isMetaclass
  158. ifTrue: [aClass instanceClass name, ' class']
  159. ifFalse: [
  160. aClass isNil
  161. ifTrue: ['nil']
  162. ifFalse: [aClass name]]
  163. !
  164. exportDefinitionOf: aClass on: aStream
  165. "Chunk format."
  166. aStream
  167. nextPutAll: (self classNameFor: aClass superclass);
  168. nextPutAll: ' subclass: #', (self classNameFor: aClass); lf;
  169. nextPutAll: ' instanceVariableNames: '''.
  170. aClass instanceVariableNames
  171. do: [:each | aStream nextPutAll: each]
  172. separatedBy: [aStream nextPutAll: ' '].
  173. aStream
  174. nextPutAll: ''''; lf;
  175. nextPutAll: ' package: ''', aClass category, '''!!'; lf.
  176. aClass comment notEmpty ifTrue: [
  177. aStream
  178. nextPutAll: '!!', (self classNameFor: aClass), ' commentStamp!!';lf;
  179. nextPutAll: (self chunkEscape: aClass comment), '!!';lf].
  180. aStream lf
  181. !
  182. exportMetaDefinitionOf: aClass on: aStream
  183. aClass class instanceVariableNames isEmpty ifFalse: [
  184. aStream
  185. nextPutAll: (self classNameFor: aClass class);
  186. nextPutAll: ' instanceVariableNames: '''.
  187. aClass class instanceVariableNames
  188. do: [:each | aStream nextPutAll: each]
  189. separatedBy: [aStream nextPutAll: ' '].
  190. aStream
  191. nextPutAll: '''!!'; lf; lf]
  192. !
  193. exportMethod: aMethod of: aClass on: aStream
  194. aStream
  195. lf; lf; nextPutAll: (self chunkEscape: aMethod source); lf;
  196. nextPutAll: '!!'
  197. !
  198. exportMethods: methods category: category of: aClass on: aStream
  199. "Issue #143: sort methods alphabetically"
  200. aStream
  201. nextPutAll: '!!', (self classNameFor: aClass);
  202. nextPutAll: ' methodsFor: ''', category, '''!!'.
  203. (methods sorted: [:a :b | a selector <= b selector]) do: [:each |
  204. self exportMethod: each of: aClass on: aStream].
  205. aStream nextPutAll: ' !!'; lf; lf
  206. !
  207. exportMethodsOf: aClass on: aStream
  208. "Issue #143: sort protocol alphabetically"
  209. | map |
  210. map := Dictionary new.
  211. aClass protocolsDo: [:category :methods |
  212. (category match: '^\*') ifFalse: [ map at: category put: methods ]].
  213. (map keys sorted: [:a :b | a <= b ]) do: [:category | | methods |
  214. methods := map at: category.
  215. self
  216. exportMethods: methods
  217. category: category
  218. of: aClass
  219. on: aStream ]
  220. !
  221. exportPackageDefinitionOf: package on: aStream
  222. "Chunk format."
  223. aStream
  224. nextPutAll: 'Smalltalk current createPackage: ''', package name,
  225. ''' properties: ', package properties storeString, '!!'; lf.
  226. !
  227. exportPackageExtensionsOf: package on: aStream
  228. "We need to override this one too since we need to group
  229. all methods in a given protocol under a leading methodsFor: chunk
  230. for that class."
  231. "Issue #143: sort protocol alphabetically"
  232. | name map |
  233. name := package name.
  234. (Package sortedClasses: Smalltalk current classes) do: [:each |
  235. {each. each class} do: [:aClass |
  236. map := Dictionary new.
  237. aClass protocolsDo: [:category :methods |
  238. (category match: '^\*', name) ifTrue: [ map at: category put: methods ]].
  239. (map keys sorted: [:a :b | a <= b ]) do: [:category | | methods |
  240. methods := map at: category.
  241. self exportMethods: methods category: category of: aClass on: aStream ]]]
  242. ! !
  243. Exporter subclass: #StrippedExporter
  244. instanceVariableNames: ''
  245. package: 'Compiler'!
  246. !StrippedExporter methodsFor: 'private'!
  247. exportDefinitionOf: aClass on: aStream
  248. aStream
  249. nextPutAll: 'smalltalk.addClass(';
  250. nextPutAll: '''', (self classNameFor: aClass), ''', ';
  251. nextPutAll: 'smalltalk.', (self classNameFor: aClass superclass);
  252. nextPutAll: ', ['.
  253. aClass instanceVariableNames
  254. do: [:each | aStream nextPutAll: '''', each, '''']
  255. separatedBy: [aStream nextPutAll: ', '].
  256. aStream
  257. nextPutAll: '], ''';
  258. nextPutAll: aClass category, '''';
  259. nextPutAll: ');'.
  260. aStream lf
  261. !
  262. exportMethod: aMethod of: aClass on: aStream
  263. aStream
  264. nextPutAll: 'smalltalk.addMethod(';lf;
  265. nextPutAll: 'unescape(''', aMethod selector asSelector escaped, '''),';lf;
  266. nextPutAll: 'smalltalk.method({';lf;
  267. nextPutAll: 'selector: unescape(''', aMethod selector escaped, '''),';lf;
  268. nextPutAll: 'fn: ', aMethod fn compiledSource;lf;
  269. nextPutAll: '}),';lf;
  270. nextPutAll: 'smalltalk.', (self classNameFor: aClass);
  271. nextPutAll: ');';lf;lf
  272. ! !
  273. Object subclass: #Importer
  274. instanceVariableNames: ''
  275. package: 'Compiler'!
  276. !Importer methodsFor: 'fileIn'!
  277. import: aStream
  278. | chunk result parser lastEmpty |
  279. parser := ChunkParser on: aStream.
  280. lastEmpty := false.
  281. [chunk := parser nextChunk.
  282. chunk isNil] whileFalse: [
  283. chunk isEmpty
  284. ifTrue: [lastEmpty := true]
  285. ifFalse: [
  286. result := Compiler new loadExpression: chunk.
  287. lastEmpty
  288. ifTrue: [
  289. lastEmpty := false.
  290. result scanFrom: parser]]]
  291. ! !
  292. Object subclass: #Node
  293. instanceVariableNames: 'nodes'
  294. package: 'Compiler'!
  295. !Node methodsFor: 'accessing'!
  296. addNode: aNode
  297. self nodes add: aNode
  298. !
  299. nodes
  300. ^nodes ifNil: [nodes := Array new]
  301. ! !
  302. !Node methodsFor: 'building'!
  303. nodes: aCollection
  304. nodes := aCollection
  305. ! !
  306. !Node methodsFor: 'testing'!
  307. isBlockNode
  308. ^false
  309. !
  310. isBlockSequenceNode
  311. ^false
  312. !
  313. isValueNode
  314. ^false
  315. ! !
  316. !Node methodsFor: 'visiting'!
  317. accept: aVisitor
  318. aVisitor visitNode: self
  319. ! !
  320. Node subclass: #AssignmentNode
  321. instanceVariableNames: 'left right'
  322. package: 'Compiler'!
  323. !AssignmentNode methodsFor: 'accessing'!
  324. left
  325. ^left
  326. !
  327. left: aNode
  328. left := aNode.
  329. left assigned: true
  330. !
  331. right
  332. ^right
  333. !
  334. right: aNode
  335. right := aNode
  336. ! !
  337. !AssignmentNode methodsFor: 'visiting'!
  338. accept: aVisitor
  339. aVisitor visitAssignmentNode: self
  340. ! !
  341. Node subclass: #BlockNode
  342. instanceVariableNames: 'parameters inlined'
  343. package: 'Compiler'!
  344. !BlockNode methodsFor: 'accessing'!
  345. inlined
  346. ^inlined ifNil: [false]
  347. !
  348. inlined: aBoolean
  349. inlined := aBoolean
  350. !
  351. parameters
  352. ^parameters ifNil: [parameters := Array new]
  353. !
  354. parameters: aCollection
  355. parameters := aCollection
  356. ! !
  357. !BlockNode methodsFor: 'testing'!
  358. isBlockNode
  359. ^true
  360. ! !
  361. !BlockNode methodsFor: 'visiting'!
  362. accept: aVisitor
  363. aVisitor visitBlockNode: self
  364. ! !
  365. Node subclass: #CascadeNode
  366. instanceVariableNames: 'receiver'
  367. package: 'Compiler'!
  368. !CascadeNode methodsFor: 'accessing'!
  369. receiver
  370. ^receiver
  371. !
  372. receiver: aNode
  373. receiver := aNode
  374. ! !
  375. !CascadeNode methodsFor: 'visiting'!
  376. accept: aVisitor
  377. aVisitor visitCascadeNode: self
  378. ! !
  379. Node subclass: #DynamicArrayNode
  380. instanceVariableNames: ''
  381. package: 'Compiler'!
  382. !DynamicArrayNode methodsFor: 'visiting'!
  383. accept: aVisitor
  384. aVisitor visitDynamicArrayNode: self
  385. ! !
  386. Node subclass: #DynamicDictionaryNode
  387. instanceVariableNames: ''
  388. package: 'Compiler'!
  389. !DynamicDictionaryNode methodsFor: 'visiting'!
  390. accept: aVisitor
  391. aVisitor visitDynamicDictionaryNode: self
  392. ! !
  393. Node subclass: #JSStatementNode
  394. instanceVariableNames: 'source'
  395. package: 'Compiler'!
  396. !JSStatementNode methodsFor: 'accessing'!
  397. source
  398. ^source ifNil: ['']
  399. !
  400. source: aString
  401. source := aString
  402. ! !
  403. !JSStatementNode methodsFor: 'visiting'!
  404. accept: aVisitor
  405. aVisitor visitJSStatementNode: self
  406. ! !
  407. Node subclass: #MethodNode
  408. instanceVariableNames: 'selector arguments source'
  409. package: 'Compiler'!
  410. !MethodNode methodsFor: 'accessing'!
  411. arguments
  412. ^arguments ifNil: [#()]
  413. !
  414. arguments: aCollection
  415. arguments := aCollection
  416. !
  417. selector
  418. ^selector
  419. !
  420. selector: aString
  421. selector := aString
  422. !
  423. source
  424. ^source
  425. !
  426. source: aString
  427. source := aString
  428. ! !
  429. !MethodNode methodsFor: 'visiting'!
  430. accept: aVisitor
  431. aVisitor visitMethodNode: self
  432. ! !
  433. Node subclass: #ReturnNode
  434. instanceVariableNames: ''
  435. package: 'Compiler'!
  436. !ReturnNode methodsFor: 'visiting'!
  437. accept: aVisitor
  438. aVisitor visitReturnNode: self
  439. ! !
  440. Node subclass: #SendNode
  441. instanceVariableNames: 'selector arguments receiver'
  442. package: 'Compiler'!
  443. !SendNode methodsFor: 'accessing'!
  444. arguments
  445. ^arguments ifNil: [arguments := #()]
  446. !
  447. arguments: aCollection
  448. arguments := aCollection
  449. !
  450. cascadeNodeWithMessages: aCollection
  451. | first |
  452. first := SendNode new
  453. selector: self selector;
  454. arguments: self arguments;
  455. yourself.
  456. ^CascadeNode new
  457. receiver: self receiver;
  458. nodes: (Array with: first), aCollection;
  459. yourself
  460. !
  461. receiver
  462. ^receiver
  463. !
  464. receiver: aNode
  465. receiver := aNode
  466. !
  467. selector
  468. ^selector
  469. !
  470. selector: aString
  471. selector := aString
  472. !
  473. valueForReceiver: anObject
  474. ^SendNode new
  475. receiver: (self receiver
  476. ifNil: [anObject]
  477. ifNotNil: [self receiver valueForReceiver: anObject]);
  478. selector: self selector;
  479. arguments: self arguments;
  480. yourself
  481. ! !
  482. !SendNode methodsFor: 'visiting'!
  483. accept: aVisitor
  484. aVisitor visitSendNode: self
  485. ! !
  486. Node subclass: #SequenceNode
  487. instanceVariableNames: 'temps'
  488. package: 'Compiler'!
  489. !SequenceNode methodsFor: 'accessing'!
  490. temps
  491. ^temps ifNil: [#()]
  492. !
  493. temps: aCollection
  494. temps := aCollection
  495. ! !
  496. !SequenceNode methodsFor: 'testing'!
  497. asBlockSequenceNode
  498. ^BlockSequenceNode new
  499. nodes: self nodes;
  500. temps: self temps;
  501. yourself
  502. ! !
  503. !SequenceNode methodsFor: 'visiting'!
  504. accept: aVisitor
  505. aVisitor visitSequenceNode: self
  506. ! !
  507. SequenceNode subclass: #BlockSequenceNode
  508. instanceVariableNames: ''
  509. package: 'Compiler'!
  510. !BlockSequenceNode methodsFor: 'testing'!
  511. isBlockSequenceNode
  512. ^true
  513. ! !
  514. !BlockSequenceNode methodsFor: 'visiting'!
  515. accept: aVisitor
  516. aVisitor visitBlockSequenceNode: self
  517. ! !
  518. Node subclass: #ValueNode
  519. instanceVariableNames: 'value'
  520. package: 'Compiler'!
  521. !ValueNode methodsFor: 'accessing'!
  522. value
  523. ^value
  524. !
  525. value: anObject
  526. value := anObject
  527. ! !
  528. !ValueNode methodsFor: 'testing'!
  529. isValueNode
  530. ^true
  531. ! !
  532. !ValueNode methodsFor: 'visiting'!
  533. accept: aVisitor
  534. aVisitor visitValueNode: self
  535. ! !
  536. ValueNode subclass: #VariableNode
  537. instanceVariableNames: 'assigned'
  538. package: 'Compiler'!
  539. !VariableNode methodsFor: 'accessing'!
  540. assigned
  541. ^assigned ifNil: [false]
  542. !
  543. assigned: aBoolean
  544. assigned := aBoolean
  545. ! !
  546. !VariableNode methodsFor: 'visiting'!
  547. accept: aVisitor
  548. aVisitor visitVariableNode: self
  549. ! !
  550. VariableNode subclass: #ClassReferenceNode
  551. instanceVariableNames: ''
  552. package: 'Compiler'!
  553. !ClassReferenceNode methodsFor: 'visiting'!
  554. accept: aVisitor
  555. aVisitor visitClassReferenceNode: self
  556. ! !
  557. Object subclass: #NodeVisitor
  558. instanceVariableNames: ''
  559. package: 'Compiler'!
  560. !NodeVisitor methodsFor: 'visiting'!
  561. visit: aNode
  562. aNode accept: self
  563. !
  564. visitAssignmentNode: aNode
  565. self visitNode: aNode
  566. !
  567. visitBlockNode: aNode
  568. self visitNode: aNode
  569. !
  570. visitBlockSequenceNode: aNode
  571. self visitSequenceNode: aNode
  572. !
  573. visitCascadeNode: aNode
  574. self visitNode: aNode
  575. !
  576. visitClassReferenceNode: aNode
  577. self
  578. nextPutAll: 'smalltalk.';
  579. nextPutAll: aNode value
  580. !
  581. visitDynamicArrayNode: aNode
  582. self visitNode: aNode
  583. !
  584. visitDynamicDictionaryNode: aNode
  585. self visitNode: aNode
  586. !
  587. visitJSStatementNode: aNode
  588. self
  589. nextPutAll: 'function(){';
  590. nextPutAll: aNode source;
  591. nextPutAll: '})()'
  592. !
  593. visitMethodNode: aNode
  594. self visitNode: aNode
  595. !
  596. visitNode: aNode
  597. !
  598. visitReturnNode: aNode
  599. self visitNode: aNode
  600. !
  601. visitSendNode: aNode
  602. self visitNode: aNode
  603. !
  604. visitSequenceNode: aNode
  605. self visitNode: aNode
  606. !
  607. visitValueNode: aNode
  608. self visitNode: aNode
  609. !
  610. visitVariableNode: aNode
  611. ! !
  612. NodeVisitor subclass: #Compiler
  613. instanceVariableNames: 'stream nestedBlocks earlyReturn currentClass currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced source argVariables'
  614. package: 'Compiler'!
  615. !Compiler methodsFor: 'accessing'!
  616. argVariables
  617. ^argVariables copy
  618. !
  619. classNameFor: aClass
  620. ^aClass isMetaclass
  621. ifTrue: [aClass instanceClass name, '.klass']
  622. ifFalse: [
  623. aClass isNil
  624. ifTrue: ['nil']
  625. ifFalse: [aClass name]]
  626. !
  627. currentClass
  628. ^currentClass
  629. !
  630. currentClass: aClass
  631. currentClass := aClass
  632. !
  633. knownVariables
  634. ^self pseudoVariables
  635. addAll: self tempVariables;
  636. addAll: self argVariables;
  637. yourself
  638. !
  639. parser
  640. ^SmalltalkParser new
  641. !
  642. pseudoVariables
  643. ^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
  644. !
  645. safeVariableNameFor: aString
  646. ^(Smalltalk current reservedWords includes: aString)
  647. ifTrue: [aString, '_']
  648. ifFalse: [aString]
  649. !
  650. source
  651. ^source ifNil: ['']
  652. !
  653. source: aString
  654. source := aString
  655. !
  656. tempVariables
  657. ^tempVariables copy
  658. !
  659. unknownVariables
  660. ^unknownVariables copy
  661. ! !
  662. !Compiler methodsFor: 'compiling'!
  663. compile: aString
  664. ^self compileNode: (self parse: aString)
  665. !
  666. compile: aString forClass: aClass
  667. self currentClass: aClass.
  668. self source: aString.
  669. ^self compile: aString
  670. !
  671. compileExpression: aString
  672. self currentClass: DoIt.
  673. self source: 'doIt ^[', aString, '] value'.
  674. ^self compileNode: (self parse: self source)
  675. !
  676. compileNode: aNode
  677. stream := '' writeStream.
  678. self visit: aNode.
  679. ^stream contents
  680. !
  681. eval: aString
  682. <return eval(aString)>
  683. !
  684. load: aString forClass: aClass
  685. | compiled |
  686. compiled := self eval: (self compile: aString forClass: aClass).
  687. self setupClass: aClass.
  688. ^compiled
  689. !
  690. loadExpression: aString
  691. | result |
  692. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  693. result := DoIt new doIt.
  694. DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
  695. ^result
  696. !
  697. parse: aString
  698. ^Smalltalk current parse: aString
  699. !
  700. parseExpression: aString
  701. ^self parse: 'doIt ^[', aString, '] value'
  702. !
  703. recompile: aClass
  704. aClass methodDictionary do: [:each || method |
  705. method := self load: each source forClass: aClass.
  706. method category: each category.
  707. aClass addCompiledMethod: method].
  708. aClass isMetaclass ifFalse: [self recompile: aClass class]
  709. !
  710. recompileAll
  711. Smalltalk current classes do: [:each |
  712. Transcript show: each; cr.
  713. [self recompile: each] valueWithTimeout: 100]
  714. !
  715. setupClass: aClass
  716. <smalltalk.init(aClass)>
  717. ! !
  718. !Compiler methodsFor: 'initialization'!
  719. initialize
  720. super initialize.
  721. stream := '' writeStream.
  722. unknownVariables := #().
  723. tempVariables := #().
  724. argVariables := #().
  725. messageSends := #().
  726. classReferenced := #()
  727. ! !
  728. !Compiler methodsFor: 'optimizations'!
  729. checkClass: aClassName for: receiver
  730. stream nextPutAll: '((($receiver = ', receiver, ').klass === smalltalk.', aClassName, ') ? '
  731. !
  732. inline: aSelector receiver: receiver argumentNodes: aCollection
  733. | inlined |
  734. inlined := false.
  735. "-- Booleans --"
  736. (aSelector = 'ifFalse:') ifTrue: [
  737. aCollection first isBlockNode ifTrue: [
  738. self checkClass: 'Boolean' for: receiver.
  739. stream nextPutAll: '(!! $receiver ? '.
  740. self visit: aCollection first.
  741. stream nextPutAll: '() : nil)'.
  742. inlined := true]].
  743. (aSelector = 'ifTrue:') ifTrue: [
  744. aCollection first isBlockNode ifTrue: [
  745. self checkClass: 'Boolean' for: receiver.
  746. stream nextPutAll: '($receiver ? '.
  747. self visit: aCollection first.
  748. stream nextPutAll: '() : nil)'.
  749. inlined := true]].
  750. (aSelector = 'ifTrue:ifFalse:') ifTrue: [
  751. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  752. self checkClass: 'Boolean' for: receiver.
  753. stream nextPutAll: '($receiver ? '.
  754. self visit: aCollection first.
  755. stream nextPutAll: '() : '.
  756. self visit: aCollection second.
  757. stream nextPutAll: '())'.
  758. inlined := true]].
  759. (aSelector = 'ifFalse:ifTrue:') ifTrue: [
  760. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  761. self checkClass: 'Boolean' for: receiver.
  762. stream nextPutAll: '(!! $receiver ? '.
  763. self visit: aCollection first.
  764. stream nextPutAll: '() : '.
  765. self visit: aCollection second.
  766. stream nextPutAll: '())'.
  767. inlined := true]].
  768. "-- Numbers --"
  769. (aSelector = '<') ifTrue: [
  770. self checkClass: 'Number' for: receiver.
  771. stream nextPutAll: '$receiver <'.
  772. self visit: aCollection first.
  773. inlined := true].
  774. (aSelector = '<=') ifTrue: [
  775. self checkClass: 'Number' for: receiver.
  776. stream nextPutAll: '$receiver <='.
  777. self visit: aCollection first.
  778. inlined := true].
  779. (aSelector = '>') ifTrue: [
  780. self checkClass: 'Number' for: receiver.
  781. stream nextPutAll: '$receiver >'.
  782. self visit: aCollection first.
  783. inlined := true].
  784. (aSelector = '>=') ifTrue: [
  785. self checkClass: 'Number' for: receiver.
  786. stream nextPutAll: '$receiver >='.
  787. self visit: aCollection first.
  788. inlined := true].
  789. (aSelector = '+') ifTrue: [
  790. self checkClass: 'Number' for: receiver.
  791. stream nextPutAll: '$receiver +'.
  792. self visit: aCollection first.
  793. inlined := true].
  794. (aSelector = '-') ifTrue: [
  795. self checkClass: 'Number' for: receiver.
  796. stream nextPutAll: '$receiver -'.
  797. self visit: aCollection first.
  798. inlined := true].
  799. (aSelector = '*') ifTrue: [
  800. self checkClass: 'Number' for: receiver.
  801. stream nextPutAll: '$receiver *'.
  802. self visit: aCollection first.
  803. inlined := true].
  804. (aSelector = '/') ifTrue: [
  805. self checkClass: 'Number' for: receiver.
  806. stream nextPutAll: '$receiver /'.
  807. self visit: aCollection first.
  808. inlined := true].
  809. ^inlined
  810. !
  811. inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
  812. | inlined |
  813. inlined := false.
  814. "-- BlockClosures --"
  815. (aSelector = 'whileTrue:') ifTrue: [
  816. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  817. stream nextPutAll: '(function(){while('.
  818. self visit: anObject.
  819. stream nextPutAll: '()) {'.
  820. self visit: aCollection first.
  821. stream nextPutAll: '()}})()'.
  822. inlined := true]].
  823. (aSelector = 'whileFalse:') ifTrue: [
  824. (anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
  825. stream nextPutAll: '(function(){while(!!'.
  826. self visit: anObject.
  827. stream nextPutAll: '()) {'.
  828. self visit: aCollection first.
  829. stream nextPutAll: '()}})()'.
  830. inlined := true]].
  831. (aSelector = 'whileTrue') ifTrue: [
  832. anObject isBlockNode ifTrue: [
  833. stream nextPutAll: '(function(){while('.
  834. self visit: anObject.
  835. stream nextPutAll: '()) {}})()'.
  836. inlined := true]].
  837. (aSelector = 'whileFalse') ifTrue: [
  838. anObject isBlockNode ifTrue: [
  839. stream nextPutAll: '(function(){while(!!'.
  840. self visit: anObject.
  841. stream nextPutAll: '()) {}})()'.
  842. inlined := true]].
  843. "-- Numbers --"
  844. (aSelector = '+') ifTrue: [
  845. (self isNode: anObject ofClass: Number) ifTrue: [
  846. self visit: anObject.
  847. stream nextPutAll: ' + '.
  848. self visit: aCollection first.
  849. inlined := true]].
  850. (aSelector = '-') ifTrue: [
  851. (self isNode: anObject ofClass: Number) ifTrue: [
  852. self visit: anObject.
  853. stream nextPutAll: ' - '.
  854. self visit: aCollection first.
  855. inlined := true]].
  856. (aSelector = '*') ifTrue: [
  857. (self isNode: anObject ofClass: Number) ifTrue: [
  858. self visit: anObject.
  859. stream nextPutAll: ' * '.
  860. self visit: aCollection first.
  861. inlined := true]].
  862. (aSelector = '/') ifTrue: [
  863. (self isNode: anObject ofClass: Number) ifTrue: [
  864. self visit: anObject.
  865. stream nextPutAll: ' / '.
  866. self visit: aCollection first.
  867. inlined := true]].
  868. (aSelector = '<') ifTrue: [
  869. (self isNode: anObject ofClass: Number) ifTrue: [
  870. self visit: anObject.
  871. stream nextPutAll: ' < '.
  872. self visit: aCollection first.
  873. inlined := true]].
  874. (aSelector = '<=') ifTrue: [
  875. (self isNode: anObject ofClass: Number) ifTrue: [
  876. self visit: anObject.
  877. stream nextPutAll: ' <= '.
  878. self visit: aCollection first.
  879. inlined := true]].
  880. (aSelector = '>') ifTrue: [
  881. (self isNode: anObject ofClass: Number) ifTrue: [
  882. self visit: anObject.
  883. stream nextPutAll: ' > '.
  884. self visit: aCollection first.
  885. inlined := true]].
  886. (aSelector = '>=') ifTrue: [
  887. (self isNode: anObject ofClass: Number) ifTrue: [
  888. self visit: anObject.
  889. stream nextPutAll: ' >= '.
  890. self visit: aCollection first.
  891. inlined := true]].
  892. "-- UndefinedObject --"
  893. (aSelector = 'ifNil:') ifTrue: [
  894. aCollection first isBlockNode ifTrue: [
  895. stream nextPutAll: '(($receiver = '.
  896. self visit: anObject.
  897. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  898. self visit: aCollection first.
  899. stream nextPutAll: '() : $receiver'.
  900. inlined := true]].
  901. (aSelector = 'ifNotNil:') ifTrue: [
  902. aCollection first isBlockNode ifTrue: [
  903. stream nextPutAll: '(($receiver = '.
  904. self visit: anObject.
  905. stream nextPutAll: ') !!= nil && $receiver !!= undefined) ? '.
  906. self visit: aCollection first.
  907. stream nextPutAll: '() : nil'.
  908. inlined := true]].
  909. (aSelector = 'ifNil:ifNotNil:') ifTrue: [
  910. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  911. stream nextPutAll: '(($receiver = '.
  912. self visit: anObject.
  913. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  914. self visit: aCollection first.
  915. stream nextPutAll: '() : '.
  916. self visit: aCollection second.
  917. stream nextPutAll: '()'.
  918. inlined := true]].
  919. (aSelector = 'ifNotNil:ifNil:') ifTrue: [
  920. (aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
  921. stream nextPutAll: '(($receiver = '.
  922. self visit: anObject.
  923. stream nextPutAll: ') == nil || $receiver == undefined) ? '.
  924. self visit: aCollection second.
  925. stream nextPutAll: '() : '.
  926. self visit: aCollection first.
  927. stream nextPutAll: '()'.
  928. inlined := true]].
  929. ^inlined
  930. !
  931. isNode: aNode ofClass: aClass
  932. ^aNode isValueNode and: [
  933. aNode value class = aClass or: [
  934. aNode value = 'self' and: [self currentClass = aClass]]]
  935. ! !
  936. !Compiler methodsFor: 'testing'!
  937. performOptimizations
  938. ^self class performOptimizations
  939. ! !
  940. !Compiler methodsFor: 'visiting'!
  941. send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
  942. ^String streamContents: [:str || tmp |
  943. tmp := stream.
  944. str nextPutAll: 'smalltalk.send('.
  945. str nextPutAll: aReceiver.
  946. str nextPutAll: ', "', aSelector asSelector, '", ['.
  947. stream := str.
  948. aCollection
  949. do: [:each | self visit: each]
  950. separatedBy: [stream nextPutAll: ', '].
  951. stream := tmp.
  952. str nextPutAll: ']'.
  953. aBoolean ifTrue: [
  954. str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass superclass)].
  955. str nextPutAll: ')']
  956. !
  957. visit: aNode
  958. aNode accept: self
  959. !
  960. visitAssignmentNode: aNode
  961. stream nextPutAll: '('.
  962. self visit: aNode left.
  963. stream nextPutAll: '='.
  964. self visit: aNode right.
  965. stream nextPutAll: ')'
  966. !
  967. visitBlockNode: aNode
  968. stream nextPutAll: '(function('.
  969. aNode parameters
  970. do: [:each |
  971. tempVariables add: each.
  972. stream nextPutAll: each]
  973. separatedBy: [stream nextPutAll: ', '].
  974. stream nextPutAll: '){'.
  975. aNode nodes do: [:each | self visit: each].
  976. stream nextPutAll: '})'
  977. !
  978. visitBlockSequenceNode: aNode
  979. | index |
  980. nestedBlocks := nestedBlocks + 1.
  981. aNode nodes isEmpty
  982. ifTrue: [
  983. stream nextPutAll: 'return nil;']
  984. ifFalse: [
  985. aNode temps do: [:each | | temp |
  986. temp := self safeVariableNameFor: each.
  987. tempVariables add: temp.
  988. stream nextPutAll: 'var ', temp, '=nil;'; lf].
  989. index := 0.
  990. aNode nodes do: [:each |
  991. index := index + 1.
  992. index = aNode nodes size ifTrue: [
  993. stream nextPutAll: 'return '].
  994. self visit: each.
  995. stream nextPutAll: ';']].
  996. nestedBlocks := nestedBlocks - 1
  997. !
  998. visitCascadeNode: aNode
  999. | index |
  1000. index := 0.
  1001. (tempVariables includes: '$rec') ifFalse: [
  1002. tempVariables add: '$rec'].
  1003. stream nextPutAll: '(function($rec){'.
  1004. aNode nodes do: [:each |
  1005. index := index + 1.
  1006. index = aNode nodes size ifTrue: [
  1007. stream nextPutAll: 'return '].
  1008. each receiver: (VariableNode new value: '$rec').
  1009. self visit: each.
  1010. stream nextPutAll: ';'].
  1011. stream nextPutAll: '})('.
  1012. self visit: aNode receiver.
  1013. stream nextPutAll: ')'
  1014. !
  1015. visitClassReferenceNode: aNode
  1016. (referencedClasses includes: aNode value) ifFalse: [
  1017. referencedClasses add: aNode value].
  1018. stream nextPutAll: '(smalltalk.', aNode value, ' || ', aNode value, ')'
  1019. !
  1020. visitDynamicArrayNode: aNode
  1021. stream nextPutAll: '['.
  1022. aNode nodes
  1023. do: [:each | self visit: each]
  1024. separatedBy: [stream nextPutAll: ','].
  1025. stream nextPutAll: ']'
  1026. !
  1027. visitDynamicDictionaryNode: aNode
  1028. stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
  1029. aNode nodes
  1030. do: [:each | self visit: each]
  1031. separatedBy: [stream nextPutAll: ','].
  1032. stream nextPutAll: '])'
  1033. !
  1034. visitFailure: aFailure
  1035. self error: aFailure asString
  1036. !
  1037. visitJSStatementNode: aNode
  1038. stream nextPutAll: (aNode source replace: '>>' with: '>')
  1039. !
  1040. visitMethodNode: aNode
  1041. | str currentSelector |
  1042. currentSelector := aNode selector asSelector.
  1043. nestedBlocks := 0.
  1044. earlyReturn := false.
  1045. messageSends := #().
  1046. referencedClasses := #().
  1047. unknownVariables := #().
  1048. tempVariables := #().
  1049. argVariables := #().
  1050. stream
  1051. nextPutAll: 'smalltalk.method({'; lf;
  1052. nextPutAll: 'selector: "', aNode selector, '",'; lf.
  1053. stream nextPutAll: 'source: unescape("', self source escaped, '"),';lf.
  1054. stream nextPutAll: 'fn: function('.
  1055. aNode arguments
  1056. do: [:each |
  1057. argVariables add: each.
  1058. stream nextPutAll: each]
  1059. separatedBy: [stream nextPutAll: ', '].
  1060. stream
  1061. nextPutAll: '){'; lf;
  1062. nextPutAll: 'var self=this;'; lf.
  1063. str := stream.
  1064. stream := '' writeStream.
  1065. aNode nodes do: [:each |
  1066. self visit: each].
  1067. earlyReturn ifTrue: [
  1068. str nextPutAll: 'try{'].
  1069. str nextPutAll: stream contents.
  1070. stream := str.
  1071. stream
  1072. lf;
  1073. nextPutAll: 'return self;'.
  1074. earlyReturn ifTrue: [
  1075. stream lf; nextPutAll: '} catch(e) {if(e.name === ''stReturn'' && e.selector === ', currentSelector printString, '){return e.fn()} throw(e)}'].
  1076. stream nextPutAll: '}'.
  1077. stream
  1078. nextPutAll: ',', String lf, 'messageSends: ';
  1079. nextPutAll: messageSends asJavascript, ','; lf;
  1080. nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
  1081. nextPutAll: 'referencedClasses: ['.
  1082. referencedClasses
  1083. do: [:each | stream nextPutAll: each printString]
  1084. separatedBy: [stream nextPutAll: ','].
  1085. stream nextPutAll: ']'.
  1086. stream nextPutAll: '})'
  1087. !
  1088. visitReturnNode: aNode
  1089. nestedBlocks > 0 ifTrue: [
  1090. earlyReturn := true].
  1091. earlyReturn
  1092. ifTrue: [
  1093. stream
  1094. nextPutAll: '(function(){throw(';
  1095. nextPutAll: '{name: ''stReturn'', selector: ';
  1096. nextPutAll: currentSelector printString;
  1097. nextPutAll: ', fn: function(){return ']
  1098. ifFalse: [stream nextPutAll: 'return '].
  1099. aNode nodes do: [:each |
  1100. self visit: each].
  1101. earlyReturn ifTrue: [
  1102. stream nextPutAll: '}})})()']
  1103. !
  1104. visitSendNode: aNode
  1105. | str receiver superSend inlined |
  1106. str := stream.
  1107. (messageSends includes: aNode selector) ifFalse: [
  1108. messageSends add: aNode selector].
  1109. stream := '' writeStream.
  1110. self visit: aNode receiver.
  1111. superSend := stream contents = 'super'.
  1112. receiver := superSend ifTrue: ['self'] ifFalse: [stream contents].
  1113. stream := str.
  1114. self performOptimizations
  1115. ifTrue: [
  1116. (self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifFalse: [
  1117. (self inline: aNode selector receiver: receiver argumentNodes: aNode arguments)
  1118. ifTrue: [stream nextPutAll: ' : ', (self send: aNode selector to: '$receiver' arguments: aNode arguments superSend: superSend), ')']
  1119. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]]]
  1120. ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]
  1121. !
  1122. visitSequenceNode: aNode
  1123. aNode temps do: [:each || temp |
  1124. temp := self safeVariableNameFor: each.
  1125. tempVariables add: temp.
  1126. stream nextPutAll: 'var ', temp, '=nil;'; lf].
  1127. aNode nodes do: [:each |
  1128. self visit: each.
  1129. stream nextPutAll: ';']
  1130. separatedBy: [stream lf]
  1131. !
  1132. visitValueNode: aNode
  1133. stream nextPutAll: aNode value asJavascript
  1134. !
  1135. visitVariableNode: aNode
  1136. | varName |
  1137. (self currentClass allInstanceVariableNames includes: aNode value)
  1138. ifTrue: [stream nextPutAll: 'self[''@', aNode value, ''']']
  1139. ifFalse: [
  1140. varName := self safeVariableNameFor: aNode value.
  1141. (self knownVariables includes: varName)
  1142. ifFalse: [
  1143. unknownVariables add: aNode value.
  1144. aNode assigned
  1145. ifTrue: [stream nextPutAll: varName]
  1146. ifFalse: [stream nextPutAll: '(typeof ', varName, ' == ''undefined'' ? nil : ', varName, ')']]
  1147. ifTrue: [
  1148. aNode value = 'thisContext'
  1149. ifTrue: [stream nextPutAll: '(smalltalk.getThisContext())']
  1150. ifFalse: [stream nextPutAll: varName]]]
  1151. ! !
  1152. Compiler class instanceVariableNames: 'performOptimizations'!
  1153. !Compiler class methodsFor: 'accessing'!
  1154. performOptimizations
  1155. ^performOptimizations ifNil: [true]
  1156. !
  1157. performOptimizations: aBoolean
  1158. performOptimizations := aBoolean
  1159. ! !
  1160. !Compiler class methodsFor: 'compiling'!
  1161. recompile: aClass
  1162. aClass methodDictionary do: [:each || method |
  1163. method := self new load: each source forClass: aClass.
  1164. method category: each category.
  1165. aClass addCompiledMethod: method].
  1166. aClass isMetaclass ifFalse: [self recompile: aClass class]
  1167. !
  1168. recompileAll
  1169. Smalltalk current classes do: [:each |
  1170. self recompile: each]
  1171. ! !