Compiler.st 36 KB

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