resin 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/amber/css/amber-normalize.css +73 -73
  2. data/amber/css/amber-normalize.less +1 -1
  3. data/amber/css/amber.css +106 -106
  4. data/amber/css/helios.css +242 -0
  5. data/amber/images/hsplitter.png +0 -0
  6. data/amber/images/vsplitter.png +0 -0
  7. data/amber/js/Benchfib.deploy.js +116 -38
  8. data/amber/js/Benchfib.js +120 -42
  9. data/amber/js/Canvas.deploy.js +674 -403
  10. data/amber/js/Canvas.js +682 -411
  11. data/amber/js/Compiler-AST.deploy.js +1150 -0
  12. data/amber/js/Compiler-AST.js +1591 -0
  13. data/amber/js/Compiler-Core.deploy.js +1562 -0
  14. data/amber/js/Compiler-Core.js +1972 -0
  15. data/amber/js/Compiler-Exceptions.deploy.js +114 -0
  16. data/amber/js/Compiler-Exceptions.js +161 -0
  17. data/amber/js/Compiler-IR.deploy.js +2326 -0
  18. data/amber/js/Compiler-IR.js +3146 -0
  19. data/amber/js/Compiler-Inlining.deploy.js +1147 -0
  20. data/amber/js/Compiler-Inlining.js +1514 -0
  21. data/amber/js/Compiler-Semantic.deploy.js +1207 -0
  22. data/amber/js/Compiler-Semantic.js +1628 -0
  23. data/amber/js/Compiler-Tests.deploy.js +646 -60
  24. data/amber/js/Compiler-Tests.js +843 -82
  25. data/amber/js/Compiler.deploy.js +1097 -159
  26. data/amber/js/Compiler.js +1414 -161
  27. data/amber/js/Examples.deploy.js +31 -15
  28. data/amber/js/Examples.js +33 -17
  29. data/amber/js/Helios-Announcements.deploy.js +127 -0
  30. data/amber/js/Helios-Announcements.js +157 -0
  31. data/amber/js/Helios-Browser.deploy.js +1473 -0
  32. data/amber/js/Helios-Browser.js +1953 -0
  33. data/amber/js/Helios-Commands.deploy.js +403 -0
  34. data/amber/js/Helios-Commands.js +563 -0
  35. data/amber/js/Helios-Core.deploy.js +1070 -0
  36. data/amber/js/Helios-Core.js +1445 -0
  37. data/amber/js/Helios-Environments.deploy.js +132 -0
  38. data/amber/js/Helios-Environments.js +179 -0
  39. data/amber/js/Helios-Inspector.deploy.js +855 -0
  40. data/amber/js/Helios-Inspector.js +1155 -0
  41. data/amber/js/Helios-KeyBindings.deploy.js +753 -0
  42. data/amber/js/Helios-KeyBindings.js +1023 -0
  43. data/amber/js/Helios-Layout.deploy.js +383 -0
  44. data/amber/js/Helios-Layout.js +523 -0
  45. data/amber/js/Helios-Workspace.deploy.js +799 -0
  46. data/amber/js/Helios-Workspace.js +1074 -0
  47. data/amber/js/IDE.deploy.js +2541 -1490
  48. data/amber/js/IDE.js +2721 -1660
  49. data/amber/js/Importer-Exporter.deploy.js +671 -0
  50. data/amber/js/Importer-Exporter.js +816 -0
  51. data/amber/js/Kernel-Announcements.deploy.js +137 -20
  52. data/amber/js/Kernel-Announcements.js +176 -22
  53. data/amber/js/Kernel-Classes.deploy.js +555 -168
  54. data/amber/js/Kernel-Classes.js +662 -205
  55. data/amber/js/Kernel-Collections.deploy.js +1403 -618
  56. data/amber/js/Kernel-Collections.js +1545 -690
  57. data/amber/js/Kernel-Exceptions.deploy.js +109 -45
  58. data/amber/js/Kernel-Exceptions.js +123 -49
  59. data/amber/js/Kernel-Methods.deploy.js +196 -81
  60. data/amber/js/Kernel-Methods.js +214 -89
  61. data/amber/js/Kernel-Objects.deploy.js +1542 -1117
  62. data/amber/js/Kernel-Objects.js +1593 -1148
  63. data/amber/js/Kernel-Tests.deploy.js +1725 -772
  64. data/amber/js/Kernel-Tests.js +2301 -1123
  65. data/amber/js/Kernel-Transcript.deploy.js +23 -25
  66. data/amber/js/Kernel-Transcript.js +24 -26
  67. data/amber/js/SUnit.deploy.js +204 -131
  68. data/amber/js/SUnit.js +222 -139
  69. data/amber/js/Spaces.deploy.js +240 -0
  70. data/amber/js/Spaces.js +326 -0
  71. data/amber/js/amber.js +26 -7
  72. data/amber/js/boot.js +65 -47
  73. data/amber/js/init.js +1 -1
  74. data/amber/js/lib/CodeMirror/amber.css +21 -21
  75. data/amber/js/lib/CodeMirror/codemirror.css +119 -13
  76. data/amber/js/lib/CodeMirror/codemirror.js +2219 -1220
  77. data/amber/js/lib/CodeMirror/smalltalk.js +134 -129
  78. data/amber/js/lib/bootstrap/css/bootstrap.css +5837 -0
  79. data/amber/js/lib/bootstrap/css/bootstrap.min.css +841 -0
  80. data/amber/js/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
  81. data/amber/js/lib/bootstrap/img/glyphicons-halflings.png +0 -0
  82. data/amber/js/lib/bootstrap/js/bootstrap.js +2038 -0
  83. data/amber/js/lib/bootstrap/js/bootstrap.min.js +7 -0
  84. data/amber/js/lib/jQuery/jquery-1.8.2.min.js +2 -0
  85. data/amber/js/lib/jQuery/jquery-ui-1.8.24.custom.min.js +125 -0
  86. data/amber/st/Compiler-AST.st +505 -0
  87. data/amber/st/Compiler-Core.st +835 -0
  88. data/amber/st/Compiler-Exceptions.st +87 -0
  89. data/amber/st/Compiler-IR.st +1097 -0
  90. data/amber/st/Compiler-Inlining.st +650 -0
  91. data/amber/st/Compiler-Semantic.st +558 -0
  92. data/amber/st/Compiler-Tests.st +285 -381
  93. data/amber/st/Compiler.st +725 -2
  94. data/amber/st/Helios-Announcements.st +104 -0
  95. data/amber/st/Helios-Browser.st +708 -0
  96. data/amber/st/Helios-Commands.st +223 -0
  97. data/amber/st/Helios-Core.st +532 -0
  98. data/amber/st/Helios-Environments.st +98 -0
  99. data/amber/st/Helios-Inspector.st +367 -0
  100. data/amber/st/Helios-KeyBindings.st +337 -0
  101. data/amber/st/Helios-Layout.st +199 -0
  102. data/amber/st/Helios-Workspace.st +367 -0
  103. data/amber/st/IDE.st +75 -53
  104. data/amber/st/Importer-Exporter.st +386 -0
  105. data/amber/st/Kernel-Announcements.st +92 -0
  106. data/amber/st/Kernel-Classes.st +137 -15
  107. data/amber/st/Kernel-Collections.st +137 -47
  108. data/amber/st/Kernel-Exceptions.st +14 -0
  109. data/amber/st/Kernel-Methods.st +9 -1
  110. data/amber/st/Kernel-Objects.st +29 -5
  111. data/amber/st/Kernel-Tests.st +545 -199
  112. data/amber/st/SUnit.st +10 -0
  113. data/amber/st/Spaces.st +142 -0
  114. data/lib/resin/app.rb +1 -1
  115. metadata +86 -31
  116. data/amber/js/lib/jQuery/jquery-1.4.4.min.js +0 -167
  117. 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
+