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