resin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+