resin 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/amber/css/amber-normalize.css +73 -73
- data/amber/css/amber-normalize.less +1 -1
- data/amber/css/amber.css +106 -106
- data/amber/css/helios.css +242 -0
- data/amber/images/hsplitter.png +0 -0
- data/amber/images/vsplitter.png +0 -0
- data/amber/js/Benchfib.deploy.js +116 -38
- data/amber/js/Benchfib.js +120 -42
- data/amber/js/Canvas.deploy.js +674 -403
- data/amber/js/Canvas.js +682 -411
- data/amber/js/Compiler-AST.deploy.js +1150 -0
- data/amber/js/Compiler-AST.js +1591 -0
- data/amber/js/Compiler-Core.deploy.js +1562 -0
- data/amber/js/Compiler-Core.js +1972 -0
- data/amber/js/Compiler-Exceptions.deploy.js +114 -0
- data/amber/js/Compiler-Exceptions.js +161 -0
- data/amber/js/Compiler-IR.deploy.js +2326 -0
- data/amber/js/Compiler-IR.js +3146 -0
- data/amber/js/Compiler-Inlining.deploy.js +1147 -0
- data/amber/js/Compiler-Inlining.js +1514 -0
- data/amber/js/Compiler-Semantic.deploy.js +1207 -0
- data/amber/js/Compiler-Semantic.js +1628 -0
- data/amber/js/Compiler-Tests.deploy.js +646 -60
- data/amber/js/Compiler-Tests.js +843 -82
- data/amber/js/Compiler.deploy.js +1097 -159
- data/amber/js/Compiler.js +1414 -161
- data/amber/js/Examples.deploy.js +31 -15
- data/amber/js/Examples.js +33 -17
- data/amber/js/Helios-Announcements.deploy.js +127 -0
- data/amber/js/Helios-Announcements.js +157 -0
- data/amber/js/Helios-Browser.deploy.js +1473 -0
- data/amber/js/Helios-Browser.js +1953 -0
- data/amber/js/Helios-Commands.deploy.js +403 -0
- data/amber/js/Helios-Commands.js +563 -0
- data/amber/js/Helios-Core.deploy.js +1070 -0
- data/amber/js/Helios-Core.js +1445 -0
- data/amber/js/Helios-Environments.deploy.js +132 -0
- data/amber/js/Helios-Environments.js +179 -0
- data/amber/js/Helios-Inspector.deploy.js +855 -0
- data/amber/js/Helios-Inspector.js +1155 -0
- data/amber/js/Helios-KeyBindings.deploy.js +753 -0
- data/amber/js/Helios-KeyBindings.js +1023 -0
- data/amber/js/Helios-Layout.deploy.js +383 -0
- data/amber/js/Helios-Layout.js +523 -0
- data/amber/js/Helios-Workspace.deploy.js +799 -0
- data/amber/js/Helios-Workspace.js +1074 -0
- data/amber/js/IDE.deploy.js +2541 -1490
- data/amber/js/IDE.js +2721 -1660
- data/amber/js/Importer-Exporter.deploy.js +671 -0
- data/amber/js/Importer-Exporter.js +816 -0
- data/amber/js/Kernel-Announcements.deploy.js +137 -20
- data/amber/js/Kernel-Announcements.js +176 -22
- data/amber/js/Kernel-Classes.deploy.js +555 -168
- data/amber/js/Kernel-Classes.js +662 -205
- data/amber/js/Kernel-Collections.deploy.js +1403 -618
- data/amber/js/Kernel-Collections.js +1545 -690
- data/amber/js/Kernel-Exceptions.deploy.js +109 -45
- data/amber/js/Kernel-Exceptions.js +123 -49
- data/amber/js/Kernel-Methods.deploy.js +196 -81
- data/amber/js/Kernel-Methods.js +214 -89
- data/amber/js/Kernel-Objects.deploy.js +1542 -1117
- data/amber/js/Kernel-Objects.js +1593 -1148
- data/amber/js/Kernel-Tests.deploy.js +1725 -772
- data/amber/js/Kernel-Tests.js +2301 -1123
- data/amber/js/Kernel-Transcript.deploy.js +23 -25
- data/amber/js/Kernel-Transcript.js +24 -26
- data/amber/js/SUnit.deploy.js +204 -131
- data/amber/js/SUnit.js +222 -139
- data/amber/js/Spaces.deploy.js +240 -0
- data/amber/js/Spaces.js +326 -0
- data/amber/js/amber.js +26 -7
- data/amber/js/boot.js +65 -47
- data/amber/js/init.js +1 -1
- data/amber/js/lib/CodeMirror/amber.css +21 -21
- data/amber/js/lib/CodeMirror/codemirror.css +119 -13
- data/amber/js/lib/CodeMirror/codemirror.js +2219 -1220
- data/amber/js/lib/CodeMirror/smalltalk.js +134 -129
- data/amber/js/lib/bootstrap/css/bootstrap.css +5837 -0
- data/amber/js/lib/bootstrap/css/bootstrap.min.css +841 -0
- data/amber/js/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/amber/js/lib/bootstrap/img/glyphicons-halflings.png +0 -0
- data/amber/js/lib/bootstrap/js/bootstrap.js +2038 -0
- data/amber/js/lib/bootstrap/js/bootstrap.min.js +7 -0
- data/amber/js/lib/jQuery/jquery-1.8.2.min.js +2 -0
- data/amber/js/lib/jQuery/jquery-ui-1.8.24.custom.min.js +125 -0
- data/amber/st/Compiler-AST.st +505 -0
- data/amber/st/Compiler-Core.st +835 -0
- data/amber/st/Compiler-Exceptions.st +87 -0
- data/amber/st/Compiler-IR.st +1097 -0
- data/amber/st/Compiler-Inlining.st +650 -0
- data/amber/st/Compiler-Semantic.st +558 -0
- data/amber/st/Compiler-Tests.st +285 -381
- data/amber/st/Compiler.st +725 -2
- data/amber/st/Helios-Announcements.st +104 -0
- data/amber/st/Helios-Browser.st +708 -0
- data/amber/st/Helios-Commands.st +223 -0
- data/amber/st/Helios-Core.st +532 -0
- data/amber/st/Helios-Environments.st +98 -0
- data/amber/st/Helios-Inspector.st +367 -0
- data/amber/st/Helios-KeyBindings.st +337 -0
- data/amber/st/Helios-Layout.st +199 -0
- data/amber/st/Helios-Workspace.st +367 -0
- data/amber/st/IDE.st +75 -53
- data/amber/st/Importer-Exporter.st +386 -0
- data/amber/st/Kernel-Announcements.st +92 -0
- data/amber/st/Kernel-Classes.st +137 -15
- data/amber/st/Kernel-Collections.st +137 -47
- data/amber/st/Kernel-Exceptions.st +14 -0
- data/amber/st/Kernel-Methods.st +9 -1
- data/amber/st/Kernel-Objects.st +29 -5
- data/amber/st/Kernel-Tests.st +545 -199
- data/amber/st/SUnit.st +10 -0
- data/amber/st/Spaces.st +142 -0
- data/lib/resin/app.rb +1 -1
- metadata +86 -31
- data/amber/js/lib/jQuery/jquery-1.4.4.min.js +0 -167
- data/amber/js/lib/jQuery/jquery-1.6.4.min.js +0 -4
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
Smalltalk current createPackage: 'Compiler-Core' properties: #{}!
|
|
2
|
+
Object subclass: #Compiler
|
|
3
|
+
instanceVariableNames: 'currentClass source unknownVariables codeGeneratorClass'
|
|
4
|
+
package: 'Compiler-Core'!
|
|
5
|
+
!Compiler commentStamp!
|
|
6
|
+
I provide the public interface for compiling Amber source code into JavaScript.
|
|
7
|
+
|
|
8
|
+
The code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`.
|
|
9
|
+
The default code generator is an instance of `InlinedCodeGenerator`!
|
|
10
|
+
|
|
11
|
+
!Compiler methodsFor: 'accessing'!
|
|
12
|
+
|
|
13
|
+
codeGeneratorClass
|
|
14
|
+
^codeGeneratorClass ifNil: [InliningCodeGenerator]
|
|
15
|
+
!
|
|
16
|
+
|
|
17
|
+
codeGeneratorClass: aClass
|
|
18
|
+
codeGeneratorClass := aClass
|
|
19
|
+
!
|
|
20
|
+
|
|
21
|
+
currentClass
|
|
22
|
+
^currentClass
|
|
23
|
+
!
|
|
24
|
+
|
|
25
|
+
currentClass: aClass
|
|
26
|
+
currentClass := aClass
|
|
27
|
+
!
|
|
28
|
+
|
|
29
|
+
source
|
|
30
|
+
^source ifNil: ['']
|
|
31
|
+
!
|
|
32
|
+
|
|
33
|
+
source: aString
|
|
34
|
+
source := aString
|
|
35
|
+
!
|
|
36
|
+
|
|
37
|
+
unknownVariables
|
|
38
|
+
^unknownVariables
|
|
39
|
+
!
|
|
40
|
+
|
|
41
|
+
unknownVariables: aCollection
|
|
42
|
+
unknownVariables := aCollection
|
|
43
|
+
! !
|
|
44
|
+
|
|
45
|
+
!Compiler methodsFor: 'compiling'!
|
|
46
|
+
|
|
47
|
+
compile: aString
|
|
48
|
+
^self compileNode: (self parse: aString)
|
|
49
|
+
!
|
|
50
|
+
|
|
51
|
+
compile: aString forClass: aClass
|
|
52
|
+
self currentClass: aClass.
|
|
53
|
+
self source: aString.
|
|
54
|
+
^self compile: aString
|
|
55
|
+
!
|
|
56
|
+
|
|
57
|
+
compileExpression: aString
|
|
58
|
+
self currentClass: DoIt.
|
|
59
|
+
self source: 'doIt ^[', aString, '] value'.
|
|
60
|
+
^self compileNode: (self parse: self source)
|
|
61
|
+
!
|
|
62
|
+
|
|
63
|
+
compileNode: aNode
|
|
64
|
+
| generator result |
|
|
65
|
+
generator := self codeGeneratorClass new.
|
|
66
|
+
generator
|
|
67
|
+
source: self source;
|
|
68
|
+
currentClass: self currentClass.
|
|
69
|
+
result := generator compileNode: aNode.
|
|
70
|
+
self unknownVariables: #().
|
|
71
|
+
^result
|
|
72
|
+
!
|
|
73
|
+
|
|
74
|
+
eval: aString
|
|
75
|
+
<return eval(aString)>
|
|
76
|
+
!
|
|
77
|
+
|
|
78
|
+
evaluateExpression: aString
|
|
79
|
+
"Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
|
|
80
|
+
| result |
|
|
81
|
+
DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
|
|
82
|
+
result := DoIt new doIt.
|
|
83
|
+
DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
|
|
84
|
+
^result
|
|
85
|
+
!
|
|
86
|
+
|
|
87
|
+
install: aString forClass: aBehavior category: anotherString
|
|
88
|
+
| compiled |
|
|
89
|
+
compiled := self eval: (self compile: aString forClass: aBehavior).
|
|
90
|
+
compiled category: anotherString.
|
|
91
|
+
aBehavior addCompiledMethod: compiled.
|
|
92
|
+
self setupClass: aBehavior.
|
|
93
|
+
^compiled
|
|
94
|
+
!
|
|
95
|
+
|
|
96
|
+
parse: aString
|
|
97
|
+
^Smalltalk current parse: aString
|
|
98
|
+
!
|
|
99
|
+
|
|
100
|
+
parseExpression: aString
|
|
101
|
+
^self parse: 'doIt ^[', aString, '] value'
|
|
102
|
+
!
|
|
103
|
+
|
|
104
|
+
recompile: aClass
|
|
105
|
+
aClass methodDictionary do: [:each |
|
|
106
|
+
console log: aClass name, ' >> ', each selector.
|
|
107
|
+
self install: each source forClass: aClass category: each category].
|
|
108
|
+
self setupClass: aClass.
|
|
109
|
+
aClass isMetaclass ifFalse: [self recompile: aClass class]
|
|
110
|
+
!
|
|
111
|
+
|
|
112
|
+
recompileAll
|
|
113
|
+
Smalltalk current classes do: [:each |
|
|
114
|
+
Transcript show: each; cr.
|
|
115
|
+
[self recompile: each] valueWithTimeout: 100]
|
|
116
|
+
!
|
|
117
|
+
|
|
118
|
+
setupClass: aClass
|
|
119
|
+
<smalltalk.init(aClass)>
|
|
120
|
+
! !
|
|
121
|
+
|
|
122
|
+
!Compiler class methodsFor: 'compiling'!
|
|
123
|
+
|
|
124
|
+
recompile: aClass
|
|
125
|
+
self new recompile: aClass
|
|
126
|
+
!
|
|
127
|
+
|
|
128
|
+
recompileAll
|
|
129
|
+
Smalltalk current classes do: [:each |
|
|
130
|
+
self recompile: each]
|
|
131
|
+
! !
|
|
132
|
+
|
|
133
|
+
Object subclass: #DoIt
|
|
134
|
+
instanceVariableNames: ''
|
|
135
|
+
package: 'Compiler-Core'!
|
|
136
|
+
!DoIt commentStamp!
|
|
137
|
+
`DoIt` is the class used to compile and evaluate expressions. See `Compiler >> evaluateExpression:`.!
|
|
138
|
+
|
|
139
|
+
Object subclass: #NodeVisitor
|
|
140
|
+
instanceVariableNames: ''
|
|
141
|
+
package: 'Compiler-Core'!
|
|
142
|
+
!NodeVisitor commentStamp!
|
|
143
|
+
I am the abstract super class of all AST node visitors.!
|
|
144
|
+
|
|
145
|
+
!NodeVisitor methodsFor: 'visiting'!
|
|
146
|
+
|
|
147
|
+
visit: aNode
|
|
148
|
+
^ aNode accept: self
|
|
149
|
+
!
|
|
150
|
+
|
|
151
|
+
visitAll: aCollection
|
|
152
|
+
^ aCollection do: [ :each | self visit: each ]
|
|
153
|
+
!
|
|
154
|
+
|
|
155
|
+
visitAssignmentNode: aNode
|
|
156
|
+
^ self visitNode: aNode
|
|
157
|
+
!
|
|
158
|
+
|
|
159
|
+
visitBlockNode: aNode
|
|
160
|
+
^ self visitNode: aNode
|
|
161
|
+
!
|
|
162
|
+
|
|
163
|
+
visitBlockSequenceNode: aNode
|
|
164
|
+
^ self visitSequenceNode: aNode
|
|
165
|
+
!
|
|
166
|
+
|
|
167
|
+
visitCascadeNode: aNode
|
|
168
|
+
^ self visitNode: aNode
|
|
169
|
+
!
|
|
170
|
+
|
|
171
|
+
visitClassReferenceNode: aNode
|
|
172
|
+
^ self visitVariableNode: aNode
|
|
173
|
+
!
|
|
174
|
+
|
|
175
|
+
visitDynamicArrayNode: aNode
|
|
176
|
+
^ self visitNode: aNode
|
|
177
|
+
!
|
|
178
|
+
|
|
179
|
+
visitDynamicDictionaryNode: aNode
|
|
180
|
+
^ self visitNode: aNode
|
|
181
|
+
!
|
|
182
|
+
|
|
183
|
+
visitJSStatementNode: aNode
|
|
184
|
+
^ self visitNode: aNode
|
|
185
|
+
!
|
|
186
|
+
|
|
187
|
+
visitMethodNode: aNode
|
|
188
|
+
^ self visitNode: aNode
|
|
189
|
+
!
|
|
190
|
+
|
|
191
|
+
visitNode: aNode
|
|
192
|
+
^ self visitAll: aNode nodes
|
|
193
|
+
!
|
|
194
|
+
|
|
195
|
+
visitReturnNode: aNode
|
|
196
|
+
^ self visitNode: aNode
|
|
197
|
+
!
|
|
198
|
+
|
|
199
|
+
visitSendNode: aNode
|
|
200
|
+
^ self visitNode: aNode
|
|
201
|
+
!
|
|
202
|
+
|
|
203
|
+
visitSequenceNode: aNode
|
|
204
|
+
^ self visitNode: aNode
|
|
205
|
+
!
|
|
206
|
+
|
|
207
|
+
visitValueNode: aNode
|
|
208
|
+
^ self visitNode: aNode
|
|
209
|
+
!
|
|
210
|
+
|
|
211
|
+
visitVariableNode: aNode
|
|
212
|
+
^ self visitNode: aNode
|
|
213
|
+
! !
|
|
214
|
+
|
|
215
|
+
NodeVisitor subclass: #AbstractCodeGenerator
|
|
216
|
+
instanceVariableNames: 'currentClass source'
|
|
217
|
+
package: 'Compiler-Core'!
|
|
218
|
+
!AbstractCodeGenerator commentStamp!
|
|
219
|
+
I am the abstract super class of all code generators and provide their common API.!
|
|
220
|
+
|
|
221
|
+
!AbstractCodeGenerator methodsFor: 'accessing'!
|
|
222
|
+
|
|
223
|
+
classNameFor: aClass
|
|
224
|
+
^aClass isMetaclass
|
|
225
|
+
ifTrue: [aClass instanceClass name, '.klass']
|
|
226
|
+
ifFalse: [
|
|
227
|
+
aClass isNil
|
|
228
|
+
ifTrue: ['nil']
|
|
229
|
+
ifFalse: [aClass name]]
|
|
230
|
+
!
|
|
231
|
+
|
|
232
|
+
currentClass
|
|
233
|
+
^currentClass
|
|
234
|
+
!
|
|
235
|
+
|
|
236
|
+
currentClass: aClass
|
|
237
|
+
currentClass := aClass
|
|
238
|
+
!
|
|
239
|
+
|
|
240
|
+
pseudoVariables
|
|
241
|
+
^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
|
|
242
|
+
!
|
|
243
|
+
|
|
244
|
+
safeVariableNameFor: aString
|
|
245
|
+
^(Smalltalk current reservedWords includes: aString)
|
|
246
|
+
ifTrue: [aString, '_']
|
|
247
|
+
ifFalse: [aString]
|
|
248
|
+
!
|
|
249
|
+
|
|
250
|
+
source
|
|
251
|
+
^source ifNil: ['']
|
|
252
|
+
!
|
|
253
|
+
|
|
254
|
+
source: aString
|
|
255
|
+
source := aString
|
|
256
|
+
! !
|
|
257
|
+
|
|
258
|
+
!AbstractCodeGenerator methodsFor: 'compiling'!
|
|
259
|
+
|
|
260
|
+
compileNode: aNode
|
|
261
|
+
self subclassResponsibility
|
|
262
|
+
! !
|
|
263
|
+
|
|
264
|
+
AbstractCodeGenerator subclass: #CodeGenerator
|
|
265
|
+
instanceVariableNames: ''
|
|
266
|
+
package: 'Compiler-Core'!
|
|
267
|
+
!CodeGenerator commentStamp!
|
|
268
|
+
I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.
|
|
269
|
+
See `InliningCodeGenerator` for an optimized JavaScript code generation.!
|
|
270
|
+
|
|
271
|
+
!CodeGenerator methodsFor: 'compiling'!
|
|
272
|
+
|
|
273
|
+
compileNode: aNode
|
|
274
|
+
| ir stream |
|
|
275
|
+
self semanticAnalyzer visit: aNode.
|
|
276
|
+
ir := self translator visit: aNode.
|
|
277
|
+
^ self irTranslator
|
|
278
|
+
visit: ir;
|
|
279
|
+
contents
|
|
280
|
+
!
|
|
281
|
+
|
|
282
|
+
irTranslator
|
|
283
|
+
^ IRJSTranslator new
|
|
284
|
+
!
|
|
285
|
+
|
|
286
|
+
semanticAnalyzer
|
|
287
|
+
^ SemanticAnalyzer on: self currentClass
|
|
288
|
+
!
|
|
289
|
+
|
|
290
|
+
translator
|
|
291
|
+
^ IRASTTranslator new
|
|
292
|
+
source: self source;
|
|
293
|
+
theClass: self currentClass;
|
|
294
|
+
yourself
|
|
295
|
+
! !
|
|
296
|
+
|
|
297
|
+
AbstractCodeGenerator subclass: #FunCodeGenerator
|
|
298
|
+
instanceVariableNames: 'stream nestedBlocks earlyReturn currentSelector unknownVariables tempVariables messageSends referencedClasses classReferenced argVariables'
|
|
299
|
+
package: 'Compiler-Core'!
|
|
300
|
+
|
|
301
|
+
!FunCodeGenerator methodsFor: 'accessing'!
|
|
302
|
+
|
|
303
|
+
argVariables
|
|
304
|
+
^argVariables copy
|
|
305
|
+
!
|
|
306
|
+
|
|
307
|
+
knownVariables
|
|
308
|
+
^self pseudoVariables
|
|
309
|
+
addAll: self tempVariables;
|
|
310
|
+
addAll: self argVariables;
|
|
311
|
+
yourself
|
|
312
|
+
!
|
|
313
|
+
|
|
314
|
+
tempVariables
|
|
315
|
+
^tempVariables copy
|
|
316
|
+
!
|
|
317
|
+
|
|
318
|
+
unknownVariables
|
|
319
|
+
^unknownVariables copy
|
|
320
|
+
! !
|
|
321
|
+
|
|
322
|
+
!FunCodeGenerator methodsFor: 'compiling'!
|
|
323
|
+
|
|
324
|
+
compileNode: aNode
|
|
325
|
+
stream := '' writeStream.
|
|
326
|
+
self visit: aNode.
|
|
327
|
+
^stream contents
|
|
328
|
+
! !
|
|
329
|
+
|
|
330
|
+
!FunCodeGenerator methodsFor: 'initialization'!
|
|
331
|
+
|
|
332
|
+
initialize
|
|
333
|
+
super initialize.
|
|
334
|
+
stream := '' writeStream.
|
|
335
|
+
unknownVariables := #().
|
|
336
|
+
tempVariables := #().
|
|
337
|
+
argVariables := #().
|
|
338
|
+
messageSends := #().
|
|
339
|
+
classReferenced := #()
|
|
340
|
+
! !
|
|
341
|
+
|
|
342
|
+
!FunCodeGenerator methodsFor: 'optimizations'!
|
|
343
|
+
|
|
344
|
+
checkClass: aClassName for: receiver
|
|
345
|
+
stream nextPutAll: '((($receiver = ', receiver, ').klass === smalltalk.', aClassName, ') ? '
|
|
346
|
+
!
|
|
347
|
+
|
|
348
|
+
inline: aSelector receiver: receiver argumentNodes: aCollection
|
|
349
|
+
| inlined |
|
|
350
|
+
inlined := false.
|
|
351
|
+
|
|
352
|
+
"-- Booleans --"
|
|
353
|
+
|
|
354
|
+
(aSelector = 'ifFalse:') ifTrue: [
|
|
355
|
+
aCollection first isBlockNode ifTrue: [
|
|
356
|
+
self checkClass: 'Boolean' for: receiver.
|
|
357
|
+
stream nextPutAll: '(!! $receiver ? '.
|
|
358
|
+
self visit: aCollection first.
|
|
359
|
+
stream nextPutAll: '() : nil)'.
|
|
360
|
+
inlined := true]].
|
|
361
|
+
|
|
362
|
+
(aSelector = 'ifTrue:') ifTrue: [
|
|
363
|
+
aCollection first isBlockNode ifTrue: [
|
|
364
|
+
self checkClass: 'Boolean' for: receiver.
|
|
365
|
+
stream nextPutAll: '($receiver ? '.
|
|
366
|
+
self visit: aCollection first.
|
|
367
|
+
stream nextPutAll: '() : nil)'.
|
|
368
|
+
inlined := true]].
|
|
369
|
+
|
|
370
|
+
(aSelector = 'ifTrue:ifFalse:') ifTrue: [
|
|
371
|
+
(aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
|
|
372
|
+
self checkClass: 'Boolean' for: receiver.
|
|
373
|
+
stream nextPutAll: '($receiver ? '.
|
|
374
|
+
self visit: aCollection first.
|
|
375
|
+
stream nextPutAll: '() : '.
|
|
376
|
+
self visit: aCollection second.
|
|
377
|
+
stream nextPutAll: '())'.
|
|
378
|
+
inlined := true]].
|
|
379
|
+
|
|
380
|
+
(aSelector = 'ifFalse:ifTrue:') ifTrue: [
|
|
381
|
+
(aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
|
|
382
|
+
self checkClass: 'Boolean' for: receiver.
|
|
383
|
+
stream nextPutAll: '(!! $receiver ? '.
|
|
384
|
+
self visit: aCollection first.
|
|
385
|
+
stream nextPutAll: '() : '.
|
|
386
|
+
self visit: aCollection second.
|
|
387
|
+
stream nextPutAll: '())'.
|
|
388
|
+
inlined := true]].
|
|
389
|
+
|
|
390
|
+
"-- Numbers --"
|
|
391
|
+
|
|
392
|
+
(aSelector = '<') ifTrue: [
|
|
393
|
+
self checkClass: 'Number' for: receiver.
|
|
394
|
+
stream nextPutAll: '$receiver <'.
|
|
395
|
+
self visit: aCollection first.
|
|
396
|
+
inlined := true].
|
|
397
|
+
|
|
398
|
+
(aSelector = '<=') ifTrue: [
|
|
399
|
+
self checkClass: 'Number' for: receiver.
|
|
400
|
+
stream nextPutAll: '$receiver <='.
|
|
401
|
+
self visit: aCollection first.
|
|
402
|
+
inlined := true].
|
|
403
|
+
|
|
404
|
+
(aSelector = '>') ifTrue: [
|
|
405
|
+
self checkClass: 'Number' for: receiver.
|
|
406
|
+
stream nextPutAll: '$receiver >'.
|
|
407
|
+
self visit: aCollection first.
|
|
408
|
+
inlined := true].
|
|
409
|
+
|
|
410
|
+
(aSelector = '>=') ifTrue: [
|
|
411
|
+
self checkClass: 'Number' for: receiver.
|
|
412
|
+
stream nextPutAll: '$receiver >='.
|
|
413
|
+
self visit: aCollection first.
|
|
414
|
+
inlined := true].
|
|
415
|
+
|
|
416
|
+
(aSelector = '+') ifTrue: [
|
|
417
|
+
self checkClass: 'Number' for: receiver.
|
|
418
|
+
stream nextPutAll: '$receiver +'.
|
|
419
|
+
self visit: aCollection first.
|
|
420
|
+
inlined := true].
|
|
421
|
+
|
|
422
|
+
(aSelector = '-') ifTrue: [
|
|
423
|
+
self checkClass: 'Number' for: receiver.
|
|
424
|
+
stream nextPutAll: '$receiver -'.
|
|
425
|
+
self visit: aCollection first.
|
|
426
|
+
inlined := true].
|
|
427
|
+
|
|
428
|
+
(aSelector = '*') ifTrue: [
|
|
429
|
+
self checkClass: 'Number' for: receiver.
|
|
430
|
+
stream nextPutAll: '$receiver *'.
|
|
431
|
+
self visit: aCollection first.
|
|
432
|
+
inlined := true].
|
|
433
|
+
|
|
434
|
+
(aSelector = '/') ifTrue: [
|
|
435
|
+
self checkClass: 'Number' for: receiver.
|
|
436
|
+
stream nextPutAll: '$receiver /'.
|
|
437
|
+
self visit: aCollection first.
|
|
438
|
+
inlined := true].
|
|
439
|
+
|
|
440
|
+
^inlined
|
|
441
|
+
!
|
|
442
|
+
|
|
443
|
+
inlineLiteral: aSelector receiverNode: anObject argumentNodes: aCollection
|
|
444
|
+
| inlined |
|
|
445
|
+
inlined := false.
|
|
446
|
+
|
|
447
|
+
"-- BlockClosures --"
|
|
448
|
+
|
|
449
|
+
(aSelector = 'whileTrue:') ifTrue: [
|
|
450
|
+
(anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
|
|
451
|
+
stream nextPutAll: '(function(){while('.
|
|
452
|
+
self visit: anObject.
|
|
453
|
+
stream nextPutAll: '()) {'.
|
|
454
|
+
self visit: aCollection first.
|
|
455
|
+
stream nextPutAll: '()}})()'.
|
|
456
|
+
inlined := true]].
|
|
457
|
+
|
|
458
|
+
(aSelector = 'whileFalse:') ifTrue: [
|
|
459
|
+
(anObject isBlockNode and: [aCollection first isBlockNode]) ifTrue: [
|
|
460
|
+
stream nextPutAll: '(function(){while(!!'.
|
|
461
|
+
self visit: anObject.
|
|
462
|
+
stream nextPutAll: '()) {'.
|
|
463
|
+
self visit: aCollection first.
|
|
464
|
+
stream nextPutAll: '()}})()'.
|
|
465
|
+
inlined := true]].
|
|
466
|
+
|
|
467
|
+
(aSelector = 'whileTrue') ifTrue: [
|
|
468
|
+
anObject isBlockNode ifTrue: [
|
|
469
|
+
stream nextPutAll: '(function(){while('.
|
|
470
|
+
self visit: anObject.
|
|
471
|
+
stream nextPutAll: '()) {}})()'.
|
|
472
|
+
inlined := true]].
|
|
473
|
+
|
|
474
|
+
(aSelector = 'whileFalse') ifTrue: [
|
|
475
|
+
anObject isBlockNode ifTrue: [
|
|
476
|
+
stream nextPutAll: '(function(){while(!!'.
|
|
477
|
+
self visit: anObject.
|
|
478
|
+
stream nextPutAll: '()) {}})()'.
|
|
479
|
+
inlined := true]].
|
|
480
|
+
|
|
481
|
+
"-- Numbers --"
|
|
482
|
+
|
|
483
|
+
(aSelector = '+') ifTrue: [
|
|
484
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
485
|
+
self visit: anObject.
|
|
486
|
+
stream nextPutAll: ' + '.
|
|
487
|
+
self visit: aCollection first.
|
|
488
|
+
inlined := true]].
|
|
489
|
+
|
|
490
|
+
(aSelector = '-') ifTrue: [
|
|
491
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
492
|
+
self visit: anObject.
|
|
493
|
+
stream nextPutAll: ' - '.
|
|
494
|
+
self visit: aCollection first.
|
|
495
|
+
inlined := true]].
|
|
496
|
+
|
|
497
|
+
(aSelector = '*') ifTrue: [
|
|
498
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
499
|
+
self visit: anObject.
|
|
500
|
+
stream nextPutAll: ' * '.
|
|
501
|
+
self visit: aCollection first.
|
|
502
|
+
inlined := true]].
|
|
503
|
+
|
|
504
|
+
(aSelector = '/') ifTrue: [
|
|
505
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
506
|
+
self visit: anObject.
|
|
507
|
+
stream nextPutAll: ' / '.
|
|
508
|
+
self visit: aCollection first.
|
|
509
|
+
inlined := true]].
|
|
510
|
+
|
|
511
|
+
(aSelector = '<') ifTrue: [
|
|
512
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
513
|
+
self visit: anObject.
|
|
514
|
+
stream nextPutAll: ' < '.
|
|
515
|
+
self visit: aCollection first.
|
|
516
|
+
inlined := true]].
|
|
517
|
+
|
|
518
|
+
(aSelector = '<=') ifTrue: [
|
|
519
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
520
|
+
self visit: anObject.
|
|
521
|
+
stream nextPutAll: ' <= '.
|
|
522
|
+
self visit: aCollection first.
|
|
523
|
+
inlined := true]].
|
|
524
|
+
|
|
525
|
+
(aSelector = '>') ifTrue: [
|
|
526
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
527
|
+
self visit: anObject.
|
|
528
|
+
stream nextPutAll: ' > '.
|
|
529
|
+
self visit: aCollection first.
|
|
530
|
+
inlined := true]].
|
|
531
|
+
|
|
532
|
+
(aSelector = '>=') ifTrue: [
|
|
533
|
+
(self isNode: anObject ofClass: Number) ifTrue: [
|
|
534
|
+
self visit: anObject.
|
|
535
|
+
stream nextPutAll: ' >= '.
|
|
536
|
+
self visit: aCollection first.
|
|
537
|
+
inlined := true]].
|
|
538
|
+
|
|
539
|
+
"-- UndefinedObject --"
|
|
540
|
+
|
|
541
|
+
(aSelector = 'ifNil:') ifTrue: [
|
|
542
|
+
aCollection first isBlockNode ifTrue: [
|
|
543
|
+
stream nextPutAll: '(($receiver = '.
|
|
544
|
+
self visit: anObject.
|
|
545
|
+
stream nextPutAll: ') == nil || $receiver == undefined) ? '.
|
|
546
|
+
self visit: aCollection first.
|
|
547
|
+
stream nextPutAll: '() : $receiver'.
|
|
548
|
+
inlined := true]].
|
|
549
|
+
|
|
550
|
+
(aSelector = 'ifNotNil:') ifTrue: [
|
|
551
|
+
aCollection first isBlockNode ifTrue: [
|
|
552
|
+
stream nextPutAll: '(($receiver = '.
|
|
553
|
+
self visit: anObject.
|
|
554
|
+
stream nextPutAll: ') !!= nil && $receiver !!= undefined) ? '.
|
|
555
|
+
self visit: aCollection first.
|
|
556
|
+
stream nextPutAll: '() : nil'.
|
|
557
|
+
inlined := true]].
|
|
558
|
+
|
|
559
|
+
(aSelector = 'ifNil:ifNotNil:') ifTrue: [
|
|
560
|
+
(aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
|
|
561
|
+
stream nextPutAll: '(($receiver = '.
|
|
562
|
+
self visit: anObject.
|
|
563
|
+
stream nextPutAll: ') == nil || $receiver == undefined) ? '.
|
|
564
|
+
self visit: aCollection first.
|
|
565
|
+
stream nextPutAll: '() : '.
|
|
566
|
+
self visit: aCollection second.
|
|
567
|
+
stream nextPutAll: '()'.
|
|
568
|
+
inlined := true]].
|
|
569
|
+
|
|
570
|
+
(aSelector = 'ifNotNil:ifNil:') ifTrue: [
|
|
571
|
+
(aCollection first isBlockNode and: [aCollection second isBlockNode]) ifTrue: [
|
|
572
|
+
stream nextPutAll: '(($receiver = '.
|
|
573
|
+
self visit: anObject.
|
|
574
|
+
stream nextPutAll: ') == nil || $receiver == undefined) ? '.
|
|
575
|
+
self visit: aCollection second.
|
|
576
|
+
stream nextPutAll: '() : '.
|
|
577
|
+
self visit: aCollection first.
|
|
578
|
+
stream nextPutAll: '()'.
|
|
579
|
+
inlined := true]].
|
|
580
|
+
|
|
581
|
+
^inlined
|
|
582
|
+
!
|
|
583
|
+
|
|
584
|
+
isNode: aNode ofClass: aClass
|
|
585
|
+
^aNode isValueNode and: [
|
|
586
|
+
aNode value class = aClass or: [
|
|
587
|
+
aNode value = 'self' and: [self currentClass = aClass]]]
|
|
588
|
+
! !
|
|
589
|
+
|
|
590
|
+
!FunCodeGenerator methodsFor: 'testing'!
|
|
591
|
+
|
|
592
|
+
performOptimizations
|
|
593
|
+
^self class performOptimizations
|
|
594
|
+
! !
|
|
595
|
+
|
|
596
|
+
!FunCodeGenerator methodsFor: 'visiting'!
|
|
597
|
+
|
|
598
|
+
send: aSelector to: aReceiver arguments: aCollection superSend: aBoolean
|
|
599
|
+
^String streamContents: [:str || tmp |
|
|
600
|
+
tmp := stream.
|
|
601
|
+
str nextPutAll: 'smalltalk.send('.
|
|
602
|
+
str nextPutAll: aReceiver.
|
|
603
|
+
str nextPutAll: ', "', aSelector asSelector, '", ['.
|
|
604
|
+
stream := str.
|
|
605
|
+
aCollection
|
|
606
|
+
do: [:each | self visit: each]
|
|
607
|
+
separatedBy: [stream nextPutAll: ', '].
|
|
608
|
+
stream := tmp.
|
|
609
|
+
str nextPutAll: ']'.
|
|
610
|
+
aBoolean ifTrue: [
|
|
611
|
+
str nextPutAll: ', smalltalk.', (self classNameFor: self currentClass), '.superclass || nil'].
|
|
612
|
+
str nextPutAll: ')']
|
|
613
|
+
!
|
|
614
|
+
|
|
615
|
+
visit: aNode
|
|
616
|
+
aNode accept: self
|
|
617
|
+
!
|
|
618
|
+
|
|
619
|
+
visitAssignmentNode: aNode
|
|
620
|
+
stream nextPutAll: '('.
|
|
621
|
+
self visit: aNode left.
|
|
622
|
+
stream nextPutAll: '='.
|
|
623
|
+
self visit: aNode right.
|
|
624
|
+
stream nextPutAll: ')'
|
|
625
|
+
!
|
|
626
|
+
|
|
627
|
+
visitBlockNode: aNode
|
|
628
|
+
stream nextPutAll: '(function('.
|
|
629
|
+
aNode parameters
|
|
630
|
+
do: [:each |
|
|
631
|
+
tempVariables add: each.
|
|
632
|
+
stream nextPutAll: each]
|
|
633
|
+
separatedBy: [stream nextPutAll: ', '].
|
|
634
|
+
stream nextPutAll: '){'.
|
|
635
|
+
aNode nodes do: [:each | self visit: each].
|
|
636
|
+
stream nextPutAll: '})'
|
|
637
|
+
!
|
|
638
|
+
|
|
639
|
+
visitBlockSequenceNode: aNode
|
|
640
|
+
| index |
|
|
641
|
+
nestedBlocks := nestedBlocks + 1.
|
|
642
|
+
aNode nodes isEmpty
|
|
643
|
+
ifTrue: [
|
|
644
|
+
stream nextPutAll: 'return nil;']
|
|
645
|
+
ifFalse: [
|
|
646
|
+
aNode temps do: [:each | | temp |
|
|
647
|
+
temp := self safeVariableNameFor: each.
|
|
648
|
+
tempVariables add: temp.
|
|
649
|
+
stream nextPutAll: 'var ', temp, '=nil;'; lf].
|
|
650
|
+
index := 0.
|
|
651
|
+
aNode nodes do: [:each |
|
|
652
|
+
index := index + 1.
|
|
653
|
+
index = aNode nodes size ifTrue: [
|
|
654
|
+
stream nextPutAll: 'return '].
|
|
655
|
+
self visit: each.
|
|
656
|
+
stream nextPutAll: ';']].
|
|
657
|
+
nestedBlocks := nestedBlocks - 1
|
|
658
|
+
!
|
|
659
|
+
|
|
660
|
+
visitCascadeNode: aNode
|
|
661
|
+
| index |
|
|
662
|
+
index := 0.
|
|
663
|
+
(tempVariables includes: '$rec') ifFalse: [
|
|
664
|
+
tempVariables add: '$rec'].
|
|
665
|
+
stream nextPutAll: '(function($rec){'.
|
|
666
|
+
aNode nodes do: [:each |
|
|
667
|
+
index := index + 1.
|
|
668
|
+
index = aNode nodes size ifTrue: [
|
|
669
|
+
stream nextPutAll: 'return '].
|
|
670
|
+
each receiver: (VariableNode new value: '$rec').
|
|
671
|
+
self visit: each.
|
|
672
|
+
stream nextPutAll: ';'].
|
|
673
|
+
stream nextPutAll: '})('.
|
|
674
|
+
self visit: aNode receiver.
|
|
675
|
+
stream nextPutAll: ')'
|
|
676
|
+
!
|
|
677
|
+
|
|
678
|
+
visitClassReferenceNode: aNode
|
|
679
|
+
(referencedClasses includes: aNode value) ifFalse: [
|
|
680
|
+
referencedClasses add: aNode value].
|
|
681
|
+
stream nextPutAll: '(smalltalk.', aNode value, ' || ', aNode value, ')'
|
|
682
|
+
!
|
|
683
|
+
|
|
684
|
+
visitDynamicArrayNode: aNode
|
|
685
|
+
stream nextPutAll: '['.
|
|
686
|
+
aNode nodes
|
|
687
|
+
do: [:each | self visit: each]
|
|
688
|
+
separatedBy: [stream nextPutAll: ','].
|
|
689
|
+
stream nextPutAll: ']'
|
|
690
|
+
!
|
|
691
|
+
|
|
692
|
+
visitDynamicDictionaryNode: aNode
|
|
693
|
+
stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
|
|
694
|
+
aNode nodes
|
|
695
|
+
do: [:each | self visit: each]
|
|
696
|
+
separatedBy: [stream nextPutAll: ','].
|
|
697
|
+
stream nextPutAll: '])'
|
|
698
|
+
!
|
|
699
|
+
|
|
700
|
+
visitFailure: aFailure
|
|
701
|
+
self error: aFailure asString
|
|
702
|
+
!
|
|
703
|
+
|
|
704
|
+
visitJSStatementNode: aNode
|
|
705
|
+
stream nextPutAll: aNode source
|
|
706
|
+
!
|
|
707
|
+
|
|
708
|
+
visitMethodNode: aNode
|
|
709
|
+
| str currentSelector |
|
|
710
|
+
currentSelector := aNode selector asSelector.
|
|
711
|
+
nestedBlocks := 0.
|
|
712
|
+
earlyReturn := false.
|
|
713
|
+
messageSends := #().
|
|
714
|
+
referencedClasses := #().
|
|
715
|
+
unknownVariables := #().
|
|
716
|
+
tempVariables := #().
|
|
717
|
+
argVariables := #().
|
|
718
|
+
stream
|
|
719
|
+
nextPutAll: 'smalltalk.method({'; lf;
|
|
720
|
+
nextPutAll: 'selector: "', aNode selector, '",'; lf.
|
|
721
|
+
stream nextPutAll: 'source: ', self source asJavascript, ',';lf.
|
|
722
|
+
stream nextPutAll: 'fn: function('.
|
|
723
|
+
aNode arguments
|
|
724
|
+
do: [:each |
|
|
725
|
+
argVariables add: each.
|
|
726
|
+
stream nextPutAll: each]
|
|
727
|
+
separatedBy: [stream nextPutAll: ', '].
|
|
728
|
+
stream
|
|
729
|
+
nextPutAll: '){'; lf;
|
|
730
|
+
nextPutAll: 'var self=this;'; lf.
|
|
731
|
+
str := stream.
|
|
732
|
+
stream := '' writeStream.
|
|
733
|
+
aNode nodes do: [:each |
|
|
734
|
+
self visit: each].
|
|
735
|
+
earlyReturn ifTrue: [
|
|
736
|
+
str nextPutAll: 'var $early={};'; lf; nextPutAll: 'try{'].
|
|
737
|
+
str nextPutAll: stream contents.
|
|
738
|
+
stream := str.
|
|
739
|
+
stream
|
|
740
|
+
lf;
|
|
741
|
+
nextPutAll: 'return self;'.
|
|
742
|
+
earlyReturn ifTrue: [
|
|
743
|
+
stream lf; nextPutAll: '} catch(e) {if(e===$early)return e[0]; throw e}'].
|
|
744
|
+
stream nextPutAll: '}'.
|
|
745
|
+
stream
|
|
746
|
+
nextPutAll: ',', String lf, 'messageSends: ';
|
|
747
|
+
nextPutAll: messageSends asJavascript, ','; lf;
|
|
748
|
+
nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
|
|
749
|
+
nextPutAll: 'referencedClasses: ['.
|
|
750
|
+
referencedClasses
|
|
751
|
+
do: [:each | stream nextPutAll: each printString]
|
|
752
|
+
separatedBy: [stream nextPutAll: ','].
|
|
753
|
+
stream nextPutAll: ']'.
|
|
754
|
+
stream nextPutAll: '})'
|
|
755
|
+
!
|
|
756
|
+
|
|
757
|
+
visitReturnNode: aNode
|
|
758
|
+
nestedBlocks > 0 ifTrue: [
|
|
759
|
+
earlyReturn := true].
|
|
760
|
+
nestedBlocks > 0
|
|
761
|
+
ifTrue: [
|
|
762
|
+
stream
|
|
763
|
+
nextPutAll: '(function(){throw $early=[']
|
|
764
|
+
ifFalse: [stream nextPutAll: 'return '].
|
|
765
|
+
aNode nodes do: [:each |
|
|
766
|
+
self visit: each].
|
|
767
|
+
nestedBlocks > 0 ifTrue: [
|
|
768
|
+
stream nextPutAll: ']})()']
|
|
769
|
+
!
|
|
770
|
+
|
|
771
|
+
visitSendNode: aNode
|
|
772
|
+
| str receiver superSend inlined |
|
|
773
|
+
str := stream.
|
|
774
|
+
(messageSends includes: aNode selector) ifFalse: [
|
|
775
|
+
messageSends add: aNode selector].
|
|
776
|
+
stream := '' writeStream.
|
|
777
|
+
self visit: aNode receiver.
|
|
778
|
+
superSend := stream contents = 'super'.
|
|
779
|
+
receiver := superSend ifTrue: ['self'] ifFalse: [stream contents].
|
|
780
|
+
stream := str.
|
|
781
|
+
|
|
782
|
+
self performOptimizations
|
|
783
|
+
ifTrue: [
|
|
784
|
+
(self inlineLiteral: aNode selector receiverNode: aNode receiver argumentNodes: aNode arguments) ifFalse: [
|
|
785
|
+
(self inline: aNode selector receiver: receiver argumentNodes: aNode arguments)
|
|
786
|
+
ifTrue: [stream nextPutAll: ' : ', (self send: aNode selector to: '$receiver' arguments: aNode arguments superSend: superSend), ')']
|
|
787
|
+
ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]]]
|
|
788
|
+
ifFalse: [stream nextPutAll: (self send: aNode selector to: receiver arguments: aNode arguments superSend: superSend)]
|
|
789
|
+
!
|
|
790
|
+
|
|
791
|
+
visitSequenceNode: aNode
|
|
792
|
+
aNode temps do: [:each || temp |
|
|
793
|
+
temp := self safeVariableNameFor: each.
|
|
794
|
+
tempVariables add: temp.
|
|
795
|
+
stream nextPutAll: 'var ', temp, '=nil;'; lf].
|
|
796
|
+
aNode nodes do: [:each |
|
|
797
|
+
self visit: each.
|
|
798
|
+
stream nextPutAll: ';']
|
|
799
|
+
separatedBy: [stream lf]
|
|
800
|
+
!
|
|
801
|
+
|
|
802
|
+
visitValueNode: aNode
|
|
803
|
+
stream nextPutAll: aNode value asJavascript
|
|
804
|
+
!
|
|
805
|
+
|
|
806
|
+
visitVariableNode: aNode
|
|
807
|
+
| varName |
|
|
808
|
+
(self currentClass allInstanceVariableNames includes: aNode value)
|
|
809
|
+
ifTrue: [stream nextPutAll: 'self[''@', aNode value, ''']']
|
|
810
|
+
ifFalse: [
|
|
811
|
+
varName := self safeVariableNameFor: aNode value.
|
|
812
|
+
(self knownVariables includes: varName)
|
|
813
|
+
ifFalse: [
|
|
814
|
+
unknownVariables add: aNode value.
|
|
815
|
+
aNode assigned
|
|
816
|
+
ifTrue: [stream nextPutAll: varName]
|
|
817
|
+
ifFalse: [stream nextPutAll: '(typeof ', varName, ' == ''undefined'' ? nil : ', varName, ')']]
|
|
818
|
+
ifTrue: [
|
|
819
|
+
aNode value = 'thisContext'
|
|
820
|
+
ifTrue: [stream nextPutAll: '(smalltalk.getThisContext())']
|
|
821
|
+
ifFalse: [stream nextPutAll: varName]]]
|
|
822
|
+
! !
|
|
823
|
+
|
|
824
|
+
FunCodeGenerator class instanceVariableNames: 'performOptimizations'!
|
|
825
|
+
|
|
826
|
+
!FunCodeGenerator class methodsFor: 'accessing'!
|
|
827
|
+
|
|
828
|
+
performOptimizations
|
|
829
|
+
^performOptimizations ifNil: [true]
|
|
830
|
+
!
|
|
831
|
+
|
|
832
|
+
performOptimizations: aBoolean
|
|
833
|
+
performOptimizations := aBoolean
|
|
834
|
+
! !
|
|
835
|
+
|