resin 0.0.1

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