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.
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
+