resin 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/README.markdown +2 -0
  2. data/amber/bin/nodecompile.js +3 -3
  3. data/amber/css/amber.css +47 -23
  4. data/amber/images/off.amber.png +0 -0
  5. data/amber/images/offHover.amber.png +0 -0
  6. data/amber/images/sprite.amber.png +0 -0
  7. data/amber/images/tinylogo.amber.png +0 -0
  8. data/amber/js/Benchfib.deploy.js +34 -34
  9. data/amber/js/Benchfib.js +49 -49
  10. data/amber/js/Canvas.deploy.js +937 -937
  11. data/amber/js/Canvas.js +1622 -1622
  12. data/amber/js/Compiler-Tests.deploy.js +97 -0
  13. data/amber/js/Compiler-Tests.js +137 -0
  14. data/amber/js/Compiler.deploy.js +1030 -924
  15. data/amber/js/Compiler.js +1613 -1467
  16. data/amber/js/Documentation.deploy.js +417 -417
  17. data/amber/js/Documentation.js +728 -728
  18. data/amber/js/Examples.deploy.js +24 -13
  19. data/amber/js/Examples.js +36 -19
  20. data/amber/js/IDE.deploy.js +1583 -1527
  21. data/amber/js/IDE.js +2586 -2510
  22. data/amber/js/Kernel-Announcements.deploy.js +19 -19
  23. data/amber/js/Kernel-Announcements.js +28 -28
  24. data/amber/js/Kernel-Classes.deploy.js +332 -229
  25. data/amber/js/Kernel-Classes.js +532 -384
  26. data/amber/js/Kernel-Collections.deploy.js +1516 -1712
  27. data/amber/js/Kernel-Collections.js +2436 -2712
  28. data/amber/js/Kernel-Exceptions.deploy.js +85 -62
  29. data/amber/js/Kernel-Exceptions.js +131 -98
  30. data/amber/js/Kernel-Methods.deploy.js +326 -378
  31. data/amber/js/Kernel-Methods.js +473 -525
  32. data/amber/js/Kernel-Objects.deploy.js +1777 -2428
  33. data/amber/js/Kernel-Objects.js +2599 -3426
  34. data/amber/js/Kernel-Tests.deploy.js +871 -772
  35. data/amber/js/Kernel-Tests.js +1207 -1083
  36. data/amber/js/Kernel-Transcript.deploy.js +57 -57
  37. data/amber/js/Kernel-Transcript.js +94 -94
  38. data/amber/js/SUnit.deploy.js +116 -116
  39. data/amber/js/SUnit.js +211 -211
  40. data/amber/js/amber.js +10 -11
  41. data/amber/js/boot.js +132 -156
  42. data/amber/js/init.js +2 -2
  43. data/amber/js/parser.js +2095 -3014
  44. data/amber/js/parser.pegjs +1 -1
  45. data/amber/st/Benchfib.st +22 -22
  46. data/amber/st/Canvas.st +471 -471
  47. data/amber/st/Compiler-Tests.st +471 -0
  48. data/amber/st/Compiler.st +858 -794
  49. data/amber/st/Examples.st +22 -5
  50. data/amber/st/IDE.st +1326 -1291
  51. data/amber/st/Kernel-Announcements.st +2 -2
  52. data/amber/st/Kernel-Classes.st +148 -90
  53. data/amber/st/Kernel-Collections.st +950 -1061
  54. data/amber/st/Kernel-Exceptions.st +33 -25
  55. data/amber/st/Kernel-Methods.st +151 -151
  56. data/amber/st/Kernel-Objects.st +891 -1036
  57. data/amber/st/Kernel-Tests.st +622 -544
  58. data/amber/st/Kernel-Transcript.st +38 -38
  59. data/amber/st/SUnit.st +53 -53
  60. metadata +27 -20
@@ -1,7 +1,7 @@
1
1
  Smalltalk current createPackage: 'Kernel-Announcements' properties: #{}!
2
2
  Object subclass: #AnnouncementSubscription
3
3
  instanceVariableNames: 'block announcementClass'
4
- category: 'Kernel-Announcements'!
4
+ package: 'Kernel-Announcements'!
5
5
 
6
6
  !AnnouncementSubscription methodsFor: 'accessing'!
7
7
 
@@ -34,7 +34,7 @@ handlesAnnouncement: anAnnouncement
34
34
 
35
35
  Object subclass: #Announcer
36
36
  instanceVariableNames: 'registry subscriptions'
37
- category: 'Kernel-Announcements'!
37
+ package: 'Kernel-Announcements'!
38
38
 
39
39
  !Announcer methodsFor: 'announcing'!
40
40
 
@@ -1,7 +1,7 @@
1
1
  Smalltalk current createPackage: 'Kernel-Classes' properties: #{}!
2
2
  Object subclass: #Behavior
3
3
  instanceVariableNames: ''
4
- category: 'Kernel-Classes'!
4
+ package: 'Kernel-Classes'!
5
5
  !Behavior commentStamp!
6
6
  Behavior is the superclass of all class objects.
7
7
 
@@ -13,16 +13,12 @@ Behavior also provides methods for compiling methods, examining the method dict
13
13
 
14
14
  !Behavior methodsFor: 'accessing'!
15
15
 
16
- name
17
- <return self.className || nil>
18
- !
19
-
20
- superclass
21
- <return self.superclass || nil>
22
- !
23
-
24
- subclasses
25
- <return smalltalk.subclasses(self)>
16
+ allInstanceVariableNames
17
+ | result |
18
+ result := self instanceVariableNames copy.
19
+ self superclass ifNotNil: [
20
+ result addAll: self superclass allInstanceVariableNames].
21
+ ^result
26
22
  !
27
23
 
28
24
  allSubclasses
@@ -33,12 +29,30 @@ allSubclasses
33
29
  ^result
34
30
  !
35
31
 
36
- withAllSubclasses
37
- ^(Array with: self) addAll: self allSubclasses; yourself
32
+ comment
33
+ ^(self basicAt: 'comment') ifNil: ['']
38
34
  !
39
35
 
40
- prototype
41
- <return self.fn.prototype>
36
+ comment: aString
37
+ self basicAt: 'comment' put: aString
38
+ !
39
+
40
+ commentStamp
41
+ ^ClassCommentReader new
42
+ class: self;
43
+ yourself
44
+ !
45
+
46
+ commentStamp: aStamp prior: prior
47
+ ^self commentStamp
48
+ !
49
+
50
+ instanceVariableNames
51
+ <return self.iVarNames>
52
+ !
53
+
54
+ methodAt: aString
55
+ <return smalltalk.methods(self)[aString]>
42
56
  !
43
57
 
44
58
  methodDictionary
@@ -58,22 +72,13 @@ methodsFor: aString
58
72
  yourself
59
73
  !
60
74
 
61
- instanceVariableNames
62
- <return self.iVarNames>
63
- !
64
-
65
- comment
66
- ^(self basicAt: 'comment') ifNil: ['']
67
- !
68
-
69
- comment: aString
70
- self basicAt: 'comment' put: aString
75
+ methodsFor: aString stamp: aStamp
76
+ "Added for compatibility, right now ignores stamp."
77
+ ^self methodsFor: aString
71
78
  !
72
79
 
73
- commentStamp
74
- ^ClassCommentReader new
75
- class: self;
76
- yourself
80
+ name
81
+ <return self.className || nil>
77
82
  !
78
83
 
79
84
  protocols
@@ -98,25 +103,20 @@ protocolsDo: aBlock
98
103
  aBlock value: category value: (methodsByCategory at: category)]
99
104
  !
100
105
 
101
- allInstanceVariableNames
102
- | result |
103
- result := self instanceVariableNames copy.
104
- self superclass ifNotNil: [
105
- result addAll: self superclass allInstanceVariableNames].
106
- ^result
106
+ prototype
107
+ <return self.fn.prototype>
107
108
  !
108
109
 
109
- methodAt: aString
110
- <return smalltalk.methods(self)[aString]>
110
+ subclasses
111
+ <return smalltalk.subclasses(self)>
111
112
  !
112
113
 
113
- methodsFor: aString stamp: aStamp
114
- "Added for compatibility, right now ignores stamp."
115
- ^self methodsFor: aString
114
+ superclass
115
+ <return self.superclass || nil>
116
116
  !
117
117
 
118
- commentStamp: aStamp prior: prior
119
- ^self commentStamp
118
+ withAllSubclasses
119
+ ^(Array with: self) addAll: self allSubclasses; yourself
120
120
  ! !
121
121
 
122
122
  !Behavior methodsFor: 'compiling'!
@@ -125,42 +125,46 @@ addCompiledMethod: aMethod
125
125
  <smalltalk.addMethod(aMethod.selector._asSelector(), aMethod, self)>
126
126
  !
127
127
 
128
- removeCompiledMethod: aMethod
129
- <delete self.fn.prototype[aMethod.selector._asSelector()];
130
- delete self.fn.prototype.methods[aMethod.selector];
131
- smalltalk.init(self);>
132
- !
133
-
134
128
  compile: aString
135
129
  self compile: aString category: ''
136
130
  !
137
131
 
138
132
  compile: aString category: anotherString
139
- | method |
140
- method := Compiler new load: aString forClass: self.
141
- method category: anotherString.
142
- self addCompiledMethod: method
133
+ Compiler new
134
+ install: aString forClass: self category: anotherString;
135
+ setupClass: self
136
+ !
137
+
138
+ removeCompiledMethod: aMethod
139
+ <delete self.fn.prototype[aMethod.selector._asSelector()];
140
+ delete self.fn.prototype.methods[aMethod.selector];
141
+ smalltalk.init(self);>
143
142
  ! !
144
143
 
145
144
  !Behavior methodsFor: 'instance creation'!
146
145
 
147
- new
148
- ^self basicNew initialize
149
- !
150
-
151
146
  basicNew
152
147
  <return new self.fn()>
148
+ !
149
+
150
+ new
151
+ ^self basicNew initialize
153
152
  ! !
154
153
 
155
154
  !Behavior methodsFor: 'testing'!
156
155
 
156
+ canUnderstand: aSelector
157
+ ^(self methodDictionary keys includes: aSelector asString) or: [
158
+ self superclass notNil and: [self superclass canUnderstand: aSelector]]
159
+ !
160
+
157
161
  inheritsFrom: aClass
158
162
  ^aClass allSubclasses includes: self
159
163
  ! !
160
164
 
161
165
  Behavior subclass: #Class
162
166
  instanceVariableNames: ''
163
- category: 'Kernel-Classes'!
167
+ package: 'Kernel-Classes'!
164
168
  !Class commentStamp!
165
169
  Class is __the__ class object.
166
170
 
@@ -173,20 +177,20 @@ category
173
177
  ^self package ifNil: ['Unclassified'] ifNotNil: [self package name]
174
178
  !
175
179
 
176
- rename: aString
177
- <
178
- smalltalk[aString] = self;
179
- delete smalltalk[self.className];
180
- self.className = aString;
181
- >
182
- !
183
-
184
180
  package
185
181
  <return self.pkg>
186
182
  !
187
183
 
188
184
  package: aPackage
189
185
  <self.pkg = aPackage>
186
+ !
187
+
188
+ rename: aString
189
+ <
190
+ smalltalk[aString] = self;
191
+ delete smalltalk[self.className];
192
+ self.className = aString;
193
+ >
190
194
  ! !
191
195
 
192
196
  !Class methodsFor: 'class creation'!
@@ -226,7 +230,7 @@ isClass
226
230
 
227
231
  Behavior subclass: #Metaclass
228
232
  instanceVariableNames: ''
229
- category: 'Kernel-Classes'!
233
+ package: 'Kernel-Classes'!
230
234
  !Metaclass commentStamp!
231
235
  Metaclass is the root of the class hierarchy.
232
236
 
@@ -258,7 +262,7 @@ isMetaclass
258
262
 
259
263
  Object subclass: #ClassBuilder
260
264
  instanceVariableNames: ''
261
- category: 'Kernel-Classes'!
265
+ package: 'Kernel-Classes'!
262
266
  !ClassBuilder commentStamp!
263
267
  ClassBuilder is responsible for compiling new classes or modifying existing classes in the system.
264
268
 
@@ -266,16 +270,16 @@ Rather than using ClassBuilder directly to compile a class, use `Class >> subcla
266
270
 
267
271
  !ClassBuilder methodsFor: 'class creation'!
268
272
 
269
- superclass: aClass subclass: aString
270
- ^self superclass: aClass subclass: aString instanceVariableNames: '' package: nil
271
- !
272
-
273
273
  class: aClass instanceVariableNames: aString
274
274
  aClass isMetaclass ifFalse: [self error: aClass name, ' is not a metaclass'].
275
275
  aClass basicAt: 'iVarNames' put: (self instanceVariableNamesFor: aString).
276
276
  self setupClass: aClass
277
277
  !
278
278
 
279
+ superclass: aClass subclass: aString
280
+ ^self superclass: aClass subclass: aString instanceVariableNames: '' package: nil
281
+ !
282
+
279
283
  superclass: aClass subclass: aString instanceVariableNames: aString2 package: aString3
280
284
  | newClass |
281
285
  newClass := self addSubclassOf: aClass
@@ -287,19 +291,11 @@ superclass: aClass subclass: aString instanceVariableNames: aString2 package: aS
287
291
 
288
292
  !ClassBuilder methodsFor: 'private'!
289
293
 
290
- instanceVariableNamesFor: aString
291
- ^(aString tokenize: ' ') reject: [:each | each isEmpty]
292
- !
293
-
294
294
  addSubclassOf: aClass named: aString instanceVariableNames: aCollection
295
295
  <smalltalk.addClass(aString, aClass, aCollection);
296
296
  return smalltalk[aString]>
297
297
  !
298
298
 
299
- setupClass: aClass
300
- <smalltalk.init(aClass);>
301
- !
302
-
303
299
  addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
304
300
  <smalltalk.addClass(aString, aClass, aCollection, packageName);
305
301
  return smalltalk[aString]>
@@ -317,20 +313,26 @@ copyClass: aClass named: aString
317
313
  self setupClass: newClass.
318
314
 
319
315
  aClass methodDictionary values do: [:each |
320
- newClass addCompiledMethod: (Compiler new load: each source forClass: newClass).
321
- (newClass methodDictionary at: each selector) category: each category].
316
+ Compiler new install: each source forClass: newClass category: each category].
322
317
 
323
318
  aClass class methodDictionary values do: [:each |
324
- newClass class addCompiledMethod: (Compiler new load: each source forClass: newClass class).
325
- (newClass class methodDictionary at: each selector) category: each category].
319
+ Compiler new install: each source forClass: newClass class category: each category].
326
320
 
327
321
  self setupClass: newClass.
328
322
  ^newClass
323
+ !
324
+
325
+ instanceVariableNamesFor: aString
326
+ ^(aString tokenize: ' ') reject: [:each | each isEmpty]
327
+ !
328
+
329
+ setupClass: aClass
330
+ <smalltalk.init(aClass);>
329
331
  ! !
330
332
 
331
333
  Object subclass: #ClassCategoryReader
332
334
  instanceVariableNames: 'class category chunkParser'
333
- category: 'Kernel-Classes'!
335
+ package: 'Kernel-Classes'!
334
336
  !ClassCategoryReader commentStamp!
335
337
  ClassCategoryReader represents a mechanism for retrieving class descriptions stored on a file.!
336
338
 
@@ -347,7 +349,8 @@ scanFrom: aChunkParser
347
349
  | chunk |
348
350
  [chunk := aChunkParser nextChunk.
349
351
  chunk isEmpty] whileFalse: [
350
- self compileMethod: chunk]
352
+ self compileMethod: chunk].
353
+ Compiler new setupClass: class
351
354
  ! !
352
355
 
353
356
  !ClassCategoryReader methodsFor: 'initialization'!
@@ -360,15 +363,12 @@ initialize
360
363
  !ClassCategoryReader methodsFor: 'private'!
361
364
 
362
365
  compileMethod: aString
363
- | method |
364
- method := Compiler new load: aString forClass: class.
365
- method category: category.
366
- class addCompiledMethod: method
366
+ Compiler new install: aString forClass: class category: category
367
367
  ! !
368
368
 
369
369
  Object subclass: #ClassCommentReader
370
370
  instanceVariableNames: 'class chunkParser'
371
- category: 'Kernel-Classes'!
371
+ package: 'Kernel-Classes'!
372
372
  !ClassCommentReader commentStamp!
373
373
  ClassCommentReader represents a mechanism for retrieving class descriptions stored on a file.
374
374
  See `ClassCategoryReader` too.!
@@ -401,3 +401,61 @@ setComment: aString
401
401
  class comment: aString
402
402
  ! !
403
403
 
404
+ Object subclass: #ClassSorterNode
405
+ instanceVariableNames: 'theClass level nodes'
406
+ package: 'Kernel-Classes'!
407
+
408
+ !ClassSorterNode methodsFor: 'accessing'!
409
+
410
+ getNodesFrom: aCollection
411
+ | children others |
412
+ children := #().
413
+ others := #().
414
+ aCollection do: [:each |
415
+ (each superclass = self theClass)
416
+ ifTrue: [children add: each]
417
+ ifFalse: [others add: each]].
418
+ nodes:= children collect: [:each |
419
+ ClassSorterNode on: each classes: others level: self level + 1]
420
+ !
421
+
422
+ level
423
+ ^level
424
+ !
425
+
426
+ level: anInteger
427
+ level := anInteger
428
+ !
429
+
430
+ nodes
431
+ ^nodes
432
+ !
433
+
434
+ theClass
435
+ ^theClass
436
+ !
437
+
438
+ theClass: aClass
439
+ theClass := aClass
440
+ ! !
441
+
442
+ !ClassSorterNode methodsFor: 'visiting'!
443
+
444
+ traverseClassesWith: aCollection
445
+ "sort classes alphabetically Issue #143"
446
+
447
+ aCollection add: self theClass.
448
+ (self nodes sorted: [:a :b | a theClass name <= b theClass name ]) do: [:aNode |
449
+ aNode traverseClassesWith: aCollection ].
450
+ ! !
451
+
452
+ !ClassSorterNode class methodsFor: 'instance creation'!
453
+
454
+ on: aClass classes: aCollection level: anInteger
455
+ ^self new
456
+ theClass: aClass;
457
+ level: anInteger;
458
+ getNodesFrom: aCollection;
459
+ yourself
460
+ ! !
461
+
@@ -1,24 +1,24 @@
1
1
  Smalltalk current createPackage: 'Kernel-Collections' properties: #{}!
2
2
  Object subclass: #Association
3
3
  instanceVariableNames: 'key value'
4
- category: 'Kernel-Collections'!
4
+ package: 'Kernel-Collections'!
5
5
 
6
6
  !Association methodsFor: 'accessing'!
7
7
 
8
- key: aKey
9
- key := aKey
10
- !
11
-
12
8
  key
13
9
  ^key
14
10
  !
15
11
 
16
- value: aValue
17
- value := aValue
12
+ key: aKey
13
+ key := aKey
18
14
  !
19
15
 
20
16
  value
21
17
  ^value
18
+ !
19
+
20
+ value: aValue
21
+ value := aValue
22
22
  ! !
23
23
 
24
24
  !Association methodsFor: 'comparing'!
@@ -48,183 +48,18 @@ key: aKey value: aValue
48
48
  yourself
49
49
  ! !
50
50
 
51
- Object subclass: #Stream
52
- instanceVariableNames: 'collection position streamSize'
53
- category: 'Kernel-Collections'!
54
-
55
- !Stream methodsFor: 'accessing'!
56
-
57
- collection
58
- ^collection
59
- !
60
-
61
- setCollection: aCollection
62
- collection := aCollection
63
- !
64
-
65
- position
66
- ^position ifNil: [position := 0]
67
- !
68
-
69
- position: anInteger
70
- position := anInteger
71
- !
72
-
73
- streamSize
74
- ^streamSize
75
- !
76
-
77
- setStreamSize: anInteger
78
- streamSize := anInteger
79
- !
80
-
81
- contents
82
- ^self collection
83
- copyFrom: 1
84
- to: self streamSize
85
- !
86
-
87
- size
88
- ^self streamSize
89
- ! !
90
-
91
- !Stream methodsFor: 'actions'!
92
-
93
- reset
94
- self position: 0
95
- !
96
-
97
- close
98
- !
99
-
100
- flush
101
- !
102
-
103
- resetContents
104
- self reset.
105
- self setStreamSize: 0
106
- ! !
107
-
108
- !Stream methodsFor: 'enumerating'!
109
-
110
- do: aBlock
111
- [self atEnd] whileFalse: [aBlock value: self next]
112
- ! !
113
-
114
- !Stream methodsFor: 'positioning'!
115
-
116
- setToEnd
117
- self position: self size
118
- !
119
-
120
- skip: anInteger
121
- self position: ((self position + anInteger) min: self size max: 0)
122
- ! !
123
-
124
- !Stream methodsFor: 'reading'!
125
-
126
- next
127
- ^self atEnd
128
- ifTrue: [nil]
129
- ifFalse: [
130
- self position: self position + 1.
131
- collection at: self position]
132
- !
133
-
134
- next: anInteger
135
- | tempCollection |
136
- tempCollection := self collection class new.
137
- anInteger timesRepeat: [
138
- self atEnd ifFalse: [
139
- tempCollection add: self next]].
140
- ^tempCollection
141
- !
142
-
143
- peek
144
- ^self atEnd ifFalse: [
145
- self collection at: self position + 1]
146
- ! !
147
-
148
- !Stream methodsFor: 'testing'!
149
-
150
- atEnd
151
- ^self position = self size
152
- !
153
-
154
- atStart
155
- ^self position = 0
156
- !
157
-
158
- isEmpty
159
- ^self size = 0
160
- ! !
161
-
162
- !Stream methodsFor: 'writing'!
163
-
164
- nextPut: anObject
165
- self position: self position + 1.
166
- self collection at: self position put: anObject.
167
- self setStreamSize: (self streamSize max: self position)
168
- !
169
-
170
- nextPutAll: aCollection
171
- aCollection do: [:each |
172
- self nextPut: each]
173
- ! !
174
-
175
- !Stream class methodsFor: 'instance creation'!
176
-
177
- on: aCollection
178
- ^self new
179
- setCollection: aCollection;
180
- setStreamSize: aCollection size;
181
- yourself
182
- ! !
183
-
184
- Object subclass: #RegularExpression
185
- instanceVariableNames: ''
186
- category: 'Kernel-Collections'!
187
-
188
- !RegularExpression methodsFor: 'evaluating'!
189
-
190
- compile: aString
191
- <return self.compile(aString)>
192
- !
193
-
194
- exec: aString
195
- <return self.exec(aString) || nil>
196
- !
197
-
198
- test: aString
199
- <return self.test(aString)>
200
- ! !
201
-
202
- !RegularExpression class methodsFor: 'instance creation'!
203
-
204
- fromString: aString flag: anotherString
205
- <return new RegExp(aString, anotherString)>
206
- !
207
-
208
- fromString: aString
209
- ^self fromString: aString flag: ''
210
- ! !
211
-
212
51
  Object subclass: #Collection
213
52
  instanceVariableNames: ''
214
- category: 'Kernel-Collections'!
53
+ package: 'Kernel-Collections'!
215
54
 
216
55
  !Collection methodsFor: 'accessing'!
217
56
 
218
- size
219
- self subclassResponsibility
220
- !
221
-
222
57
  readStream
223
58
  ^self stream
224
59
  !
225
60
 
226
- writeStream
227
- ^self stream
61
+ size
62
+ self subclassResponsibility
228
63
  !
229
64
 
230
65
  stream
@@ -233,6 +68,10 @@ stream
233
68
 
234
69
  streamClass
235
70
  ^self class streamClass
71
+ !
72
+
73
+ writeStream
74
+ ^self stream
236
75
  ! !
237
76
 
238
77
  !Collection methodsFor: 'adding/removing'!
@@ -261,16 +100,16 @@ asArray
261
100
  ^Array withAll: self
262
101
  !
263
102
 
264
- asSet
265
- ^Set withAll: self
103
+ asJSON
104
+ ^self asArray collect: [:each | each asJSON]
266
105
  !
267
106
 
268
107
  asOrderedCollection
269
108
  ^self asArray
270
109
  !
271
110
 
272
- asJSON
273
- ^self asArray collect: [:each | each asJSON]
111
+ asSet
112
+ ^Set withAll: self
274
113
  ! !
275
114
 
276
115
  !Collection methodsFor: 'copying'!
@@ -298,10 +137,6 @@ copyWithoutAll: aCollection
298
137
 
299
138
  !Collection methodsFor: 'enumerating'!
300
139
 
301
- do: aBlock
302
- <for(var i=0;i<self.length;i++){aBlock(self[i]);}>
303
- !
304
-
305
140
  collect: aBlock
306
141
  | newCollection |
307
142
  newCollection := self class new.
@@ -323,6 +158,10 @@ detect: aBlock ifNone: anotherBlock
323
158
  >
324
159
  !
325
160
 
161
+ do: aBlock
162
+ <for(var i=0;i<self.length;i++){aBlock(self[i]);}>
163
+ !
164
+
326
165
  do: aBlock separatedBy: anotherBlock
327
166
  | first |
328
167
  first := true.
@@ -362,6 +201,18 @@ errorNotFound
362
201
 
363
202
  !Collection methodsFor: 'testing'!
364
203
 
204
+ ifEmpty: aBlock
205
+ "Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: self classifyMethodAs:
206
+ (myProtocol ifEmpty: ['As yet unclassified'])"
207
+ ^ self isEmpty
208
+ ifTrue: [ aBlock value ]
209
+ ifFalse: [ self ]
210
+ !
211
+
212
+ ifNotEmpty: aBlock
213
+ self notEmpty ifTrue: aBlock.
214
+ !
215
+
365
216
  includes: anObject
366
217
  <
367
218
  var i = self.length;
@@ -372,24 +223,12 @@ includes: anObject
372
223
  >
373
224
  !
374
225
 
375
- notEmpty
376
- ^self isEmpty not
377
- !
378
-
379
226
  isEmpty
380
227
  ^self size = 0
381
228
  !
382
229
 
383
- ifNotEmpty: aBlock
384
- self notEmpty ifTrue: aBlock.
385
- !
386
-
387
- ifEmpty: aBlock
388
- "Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: self classifyMethodAs:
389
- (myProtocol ifEmpty: ['As yet unclassified'])"
390
- ^ self isEmpty
391
- ifTrue: [ aBlock value ]
392
- ifFalse: [ self ]
230
+ notEmpty
231
+ ^self isEmpty not
393
232
  ! !
394
233
 
395
234
  !Collection class methodsFor: 'accessing'!
@@ -400,6 +239,10 @@ streamClass
400
239
 
401
240
  !Collection class methodsFor: 'instance creation'!
402
241
 
242
+ new: anInteger
243
+ ^self new
244
+ !
245
+
403
246
  with: anObject
404
247
  ^self new
405
248
  add: anObject;
@@ -425,665 +268,488 @@ withAll: aCollection
425
268
  ^self new
426
269
  addAll: aCollection;
427
270
  yourself
428
- !
429
-
430
- new: anInteger
431
- ^self new
432
271
  ! !
433
272
 
434
- Collection subclass: #SequenceableCollection
273
+ Collection subclass: #HashedCollection
435
274
  instanceVariableNames: ''
436
- category: 'Kernel-Collections'!
275
+ package: 'Kernel-Collections'!
276
+ !HashedCollection commentStamp!
277
+ A HashedCollection is a traditional JavaScript object, or a Smalltalk Dictionary.
437
278
 
438
- !SequenceableCollection methodsFor: 'accessing'!
279
+ Unlike a Dictionary, it can only have strings as keys.!
439
280
 
440
- at: anIndex
441
- ^self at: anIndex ifAbsent: [
442
- self errorNotFound]
281
+ !HashedCollection methodsFor: 'accessing'!
282
+
283
+ associations
284
+ | associations |
285
+ associations := #().
286
+ self keys do: [:each |
287
+ associations add: (Association key: each value: (self at: each))].
288
+ ^associations
443
289
  !
444
290
 
445
- at: anIndex ifAbsent: aBlock
446
- self subclassResponsibility
291
+ at: aKey
292
+ ^self at: aKey ifAbsent: [self errorNotFound]
447
293
  !
448
294
 
449
- at: anIndex put: anObject
450
- self subclassResponsibility
295
+ at: aKey ifAbsent: aBlock
296
+ ^(self includesKey: aKey)
297
+ ifTrue: [self basicAt: aKey]
298
+ ifFalse: aBlock
451
299
  !
452
300
 
453
- first
454
- ^self at: 1
301
+ at: aKey ifAbsentPut: aBlock
302
+ ^self at: aKey ifAbsent: [
303
+ self at: aKey put: aBlock value]
455
304
  !
456
305
 
457
- fourth
458
- ^self at: 4
306
+ at: aKey ifPresent: aBlock
307
+ ^(self basicAt: aKey) ifNotNil: [aBlock value: (self at: aKey)]
459
308
  !
460
309
 
461
- last
462
- ^self at: self size
310
+ at: aKey ifPresent: aBlock ifAbsent: anotherBlock
311
+ ^(self basicAt: aKey)
312
+ ifNil: anotherBlock
313
+ ifNotNil: [aBlock value: (self at: aKey)]
463
314
  !
464
315
 
465
- second
466
- ^self at: 2
316
+ at: aKey put: aValue
317
+ ^self basicAt: aKey put: aValue
467
318
  !
468
319
 
469
- third
470
- ^self at: 3
320
+ keys
321
+ <
322
+ if ('function'===typeof Object.keys) return Object.keys(self);
323
+ var keys = [];
324
+ for(var i in self) {
325
+ if(self.hasOwnProperty(i)) {
326
+ keys.push(i);
327
+ }
328
+ };
329
+ return keys;
330
+ >
471
331
  !
472
332
 
473
- allButFirst
474
- ^self copyFrom: 2 to: self size
333
+ size
334
+ ^self keys size
475
335
  !
476
336
 
477
- allButLast
478
- ^self copyFrom: 1 to: self size - 1
479
- !
337
+ values
338
+ ^self keys collect: [:each | self at: each]
339
+ ! !
480
340
 
481
- indexOf: anObject
482
- ^self indexOf: anObject ifAbsent: [self errorNotFound]
483
- !
341
+ !HashedCollection methodsFor: 'adding/removing'!
484
342
 
485
- indexOf: anObject ifAbsent: aBlock
486
- <
487
- for(var i=0;i<self.length;i++){
488
- if(self[i].__eq(anObject)) {return i+1}
489
- }
490
- return aBlock();
491
- >
343
+ add: anAssociation
344
+ self at: anAssociation key put: anAssociation value
492
345
  !
493
346
 
494
- indexOf: anObject startingAt: start ifAbsent: aBlock
495
- <
496
- for(var i=start-1;i<self.length;i++){
497
- if(self[i].__eq(anObject)) {return i+1}
498
- }
499
- return aBlock();
500
- >
347
+ addAll: aHashedCollection
348
+ super addAll: aHashedCollection associations.
349
+ ^aHashedCollection
501
350
  !
502
351
 
503
- indexOf: anObject startingAt: start
504
- "Answer the index of the first occurence of anElement after start
505
- within the receiver. If the receiver does not contain anElement,
506
- answer 0."
507
- ^self indexOf: anObject startingAt: start ifAbsent: [0]
352
+ remove: aKey ifAbsent: aBlock
353
+ ^self removeKey: aKey ifAbsent: aBlock
508
354
  !
509
355
 
510
- atRandom
511
- ^ self at: self size atRandom
356
+ removeKey: aKey
357
+ ^self remove: aKey
512
358
  !
513
359
 
514
- first: n
515
- "Answer the first n elements of the receiver.
516
- Raise an error if there are not enough elements."
517
-
518
- ^ self copyFrom: 1 to: n
360
+ removeKey: aKey ifAbsent: aBlock
361
+ ^(self includesKey: aKey)
362
+ ifFalse: [aBlock value]
363
+ ifTrue: [self basicDelete: aKey]
519
364
  ! !
520
365
 
521
- !SequenceableCollection methodsFor: 'adding'!
522
-
523
- removeLast
524
- self remove: self last
525
- !
366
+ !HashedCollection methodsFor: 'comparing'!
526
367
 
527
- addLast: anObject
528
- self add: anObject
368
+ = aHashedCollection
369
+ self class = aHashedCollection class ifFalse: [^false].
370
+ self size = aHashedCollection size ifFalse: [^false].
371
+ ^self associations = aHashedCollection associations
529
372
  ! !
530
373
 
531
- !SequenceableCollection methodsFor: 'comparing'!
532
-
533
- = aCollection
534
- (self class = aCollection class and: [
535
- self size = aCollection size]) ifFalse: [^false].
536
- self withIndexDo: [:each :i |
537
- (aCollection at: i) = each ifFalse: [^false]].
538
- ^true
539
- ! !
374
+ !HashedCollection methodsFor: 'converting'!
540
375
 
541
- !SequenceableCollection methodsFor: 'converting'!
376
+ asDictionary
377
+ ^Dictionary fromPairs: self associations
378
+ !
542
379
 
543
- reversed
544
- self subclassResponsibility
380
+ asJSON
381
+ | c |
382
+ c := self class new.
383
+ self keysAndValuesDo: [:key :value |
384
+ c at: key put: value asJSON].
385
+ ^c
545
386
  ! !
546
387
 
547
- !SequenceableCollection methodsFor: 'copying'!
388
+ !HashedCollection methodsFor: 'copying'!
548
389
 
549
- copyFrom: anIndex to: anotherIndex
550
- | range newCollection |
551
- range := anIndex to: anotherIndex.
552
- newCollection := self class new: range size.
553
- range withIndexDo: [:each :i |
554
- newCollection at: i put: (self at: each)].
555
- ^newCollection
390
+ , aCollection
391
+ self shouldNotImplement
556
392
  !
557
393
 
558
- shallowCopy
559
- | newCollection |
560
- newCollection := self class new: self size.
561
- self withIndexDo: [ :each :index |
562
- newCollection at: index put: each].
563
- ^newCollection
394
+ copyFrom: anIndex to: anotherIndex
395
+ self shouldNotImplement
564
396
  !
565
397
 
566
398
  deepCopy
567
- | newCollection |
568
- newCollection := self class new: self size.
569
- self withIndexDo: [:each :index |
570
- newCollection at: index put: each deepCopy].
571
- ^newCollection
572
- ! !
573
-
574
- !SequenceableCollection methodsFor: 'enumerating'!
575
-
576
- withIndexDo: aBlock
577
- <for(var i=0;i<self.length;i++){aBlock(self[i], i+1);}>
578
- ! !
579
-
580
- !SequenceableCollection methodsFor: 'printing'!
581
-
582
- printString
583
- | str |
584
- str := '' writeStream.
585
- str nextPutAll: super printString, ' ('.
586
- self
587
- do: [:each | str nextPutAll: each printString]
588
- separatedBy: [str nextPutAll: ' '].
589
- str nextPutAll: ')'.
590
- ^str contents
591
- ! !
592
-
593
- SequenceableCollection subclass: #CharacterArray
594
- instanceVariableNames: ''
595
- category: 'Kernel-Collections'!
596
-
597
- !CharacterArray methodsFor: 'accessing'!
399
+ | copy |
400
+ copy := self class new.
401
+ self associationsDo: [:each |
402
+ copy at: each key put: each value deepCopy].
403
+ ^copy
404
+ !
598
405
 
599
- at: anIndex put: anObject
600
- self errorReadOnly
406
+ shallowCopy
407
+ | copy |
408
+ copy := self class new.
409
+ self associationsDo: [:each |
410
+ copy at: each key put: each value].
411
+ ^copy
601
412
  ! !
602
413
 
603
- !CharacterArray methodsFor: 'adding'!
414
+ !HashedCollection methodsFor: 'enumerating'!
604
415
 
605
- add: anObject
606
- self errorReadOnly
416
+ associationsDo: aBlock
417
+ self associations do: aBlock
607
418
  !
608
419
 
609
- remove: anObject
610
- self errorReadOnly
611
- ! !
612
-
613
- !CharacterArray methodsFor: 'converting'!
420
+ collect: aBlock
421
+ | newDict |
422
+ newDict := self class new.
423
+ self keysAndValuesDo: [:key :value |
424
+ newDict at: key put: (aBlock value: value)].
425
+ ^newDict
426
+ !
614
427
 
615
- asString
616
- ^self subclassResponsibility
428
+ detect: aBlock ifNone: anotherBlock
429
+ ^self values detect: aBlock ifNone: anotherBlock
617
430
  !
618
431
 
619
- asNumber
620
- ^self asString asNumber
432
+ do: aBlock
433
+ self values do: aBlock
621
434
  !
622
435
 
623
- asUppercase
624
- ^self class fromString: self asString asUppercase
436
+ includes: anObject
437
+ ^self values includes: anObject
625
438
  !
626
439
 
627
- asSymbol
628
- ^self subclassResponsibility
440
+ keysAndValuesDo: aBlock
441
+ self associationsDo: [:each |
442
+ aBlock value: each key value: each value]
629
443
  !
630
444
 
631
- asLowercase
632
- ^self class fromString: self asString asLowercase
445
+ select: aBlock
446
+ | newDict |
447
+ newDict := self class new.
448
+ self keysAndValuesDo: [:key :value |
449
+ (aBlock value: value) ifTrue: [newDict at: key put: value]].
450
+ ^newDict
633
451
  ! !
634
452
 
635
- !CharacterArray methodsFor: 'copying'!
453
+ !HashedCollection methodsFor: 'printing'!
636
454
 
637
- , aString
638
- ^self asString, aString asString
455
+ printString
456
+ ^String streamContents: [:aStream|
457
+ aStream
458
+ nextPutAll: super printString;
459
+ nextPutAll: '('.
460
+ self associations
461
+ do: [:anAssociation|
462
+ aStream
463
+ nextPutAll: anAssociation key printString;
464
+ nextPutAll: ' -> ';
465
+ nextPutAll: anAssociation value printString]
466
+ separatedBy: [aStream nextPutAll: ' , '].
467
+ aStream nextPutAll: ')']
468
+ !
469
+
470
+ storeOn: aStream
471
+ aStream nextPutAll: '#{'.
472
+ self associations
473
+ do: [:each | each storeOn: aStream]
474
+ separatedBy: [ aStream nextPutAll: '. '].
475
+ aStream nextPutAll: '}'
639
476
  ! !
640
477
 
641
- !CharacterArray methodsFor: 'error handling'!
478
+ !HashedCollection methodsFor: 'testing'!
642
479
 
643
- errorReadOnly
644
- self error: 'Object is read-only'
480
+ includesKey: aKey
481
+ <return self.hasOwnProperty(aKey)>
645
482
  ! !
646
483
 
647
- !CharacterArray methodsFor: 'printing'!
484
+ !HashedCollection class methodsFor: 'instance creation'!
648
485
 
649
- printString
650
- ^self asString printString
486
+ fromPairs: aCollection
487
+ | dict |
488
+ dict := self new.
489
+ aCollection do: [:each | dict add: each].
490
+ ^dict
651
491
  ! !
652
492
 
653
- !CharacterArray class methodsFor: 'instance creation'!
493
+ HashedCollection subclass: #Dictionary
494
+ instanceVariableNames: 'keys values'
495
+ package: 'Kernel-Collections'!
654
496
 
655
- fromString: aString
656
- self subclassResponsibility
657
- ! !
497
+ !Dictionary methodsFor: 'accessing'!
658
498
 
659
- CharacterArray subclass: #String
660
- instanceVariableNames: ''
661
- category: 'Kernel-Collections'!
499
+ at: aKey ifAbsent: aBlock
500
+ <
501
+ var index;
502
+ for(var i=0;i<self['@keys'].length;i++){
503
+ if(self['@keys'][i].__eq(aKey)) {index = i;}
504
+ };
505
+ if(typeof index === 'undefined') {
506
+ return aBlock();
507
+ } else {
508
+ return self['@values'][index];
509
+ }
510
+ >
511
+ !
662
512
 
663
- !String methodsFor: 'accessing'!
513
+ at: aKey put: aValue
514
+ <
515
+ var index = self['@keys'].indexOf(aKey);
516
+ if(index === -1) {
517
+ self['@values'].push(aValue);
518
+ self['@keys'].push(aKey);
519
+ } else {
520
+ self['@values'][index] = aValue;
521
+ };
664
522
 
665
- size
666
- <return self.length>
523
+ return aValue;
524
+ >
667
525
  !
668
526
 
669
- at: anIndex ifAbsent: aBlock
670
- <return self[anIndex - 1] || aBlock()>
527
+ keys
528
+ ^keys copy
671
529
  !
672
530
 
673
- escaped
674
- <return escape(self)>
675
- !
531
+ values
532
+ ^values copy
533
+ ! !
676
534
 
677
- unescaped
678
- <return unescape(self)>
679
- !
535
+ !Dictionary methodsFor: 'adding/removing'!
680
536
 
681
- asciiValue
682
- <return self.charCodeAt(0);>
537
+ removeKey: aKey ifAbsent: aBlock
538
+ <
539
+ var index = self['@keys'].indexOf(aKey);
540
+ if(index === -1) {
541
+ return aBlock()
542
+ } else {
543
+ var value;
544
+ self['@keys'].splice(index, 1);
545
+ value = self['@values'].splice(index, 1);
546
+ return value[0];
547
+ };
548
+ >
683
549
  ! !
684
550
 
685
- !String methodsFor: 'comparing'!
551
+ !Dictionary methodsFor: 'converting'!
686
552
 
687
- = aString
688
- aString class = self class ifFalse: [^false].
689
- <return String(self) === String(aString)>
553
+ asHashedCollection
554
+ ^HashedCollection fromPairs: self associations
690
555
  !
691
556
 
692
- > aString
693
- <return String(self) >> aString._asString()>
694
- !
557
+ asJSON
558
+ ^self asHashedCollection asJSON
559
+ ! !
695
560
 
696
- < aString
697
- <return String(self) < aString._asString()>
698
- !
561
+ !Dictionary methodsFor: 'initialization'!
699
562
 
700
- >= aString
701
- <return String(self) >>= aString._asString()>
702
- !
563
+ initialize
564
+ super initialize.
565
+ keys := #().
566
+ values := #()
567
+ ! !
703
568
 
704
- <= aString
705
- <return String(self) <= aString._asString()>
569
+ !Dictionary methodsFor: 'testing'!
570
+
571
+ includesKey: aKey
572
+ ^keys includes: aKey
706
573
  ! !
707
574
 
708
- !String methodsFor: 'converting'!
575
+ Collection subclass: #SequenceableCollection
576
+ instanceVariableNames: ''
577
+ package: 'Kernel-Collections'!
709
578
 
710
- asSelector
711
- "If you change this method, change smalltalk.convertSelector too (see js/boot.js file)"
579
+ !SequenceableCollection methodsFor: 'accessing'!
712
580
 
713
- | selector |
714
- selector := '_', self.
715
- selector := selector replace: ':' with: '_'.
716
- selector := selector replace: '[+]' with: '_plus'.
717
- selector := selector replace: '-' with: '_minus'.
718
- selector := selector replace: '[*]' with: '_star'.
719
- selector := selector replace: '[/]' with: '_slash'.
720
- selector := selector replace: '>' with: '_gt'.
721
- selector := selector replace: '<' with: '_lt'.
722
- selector := selector replace: '=' with: '_eq'.
723
- selector := selector replace: ',' with: '_comma'.
724
- selector := selector replace: '[@]' with: '_at'.
725
- ^selector
581
+ allButFirst
582
+ ^self copyFrom: 2 to: self size
726
583
  !
727
584
 
728
- asJavascript
729
- <
730
- if(self.search(/^[a-zA-Z0-9_:.$ ]*$/) == -1)
731
- return "unescape(\"" + escape(self) + "\")";
732
- else
733
- return "\"" + self + "\"";
734
- >
585
+ allButLast
586
+ ^self copyFrom: 1 to: self size - 1
735
587
  !
736
588
 
737
- tokenize: aString
738
- <return self.split(aString)>
589
+ at: anIndex
590
+ ^self at: anIndex ifAbsent: [
591
+ self errorNotFound]
739
592
  !
740
593
 
741
- asString
742
- ^self
594
+ at: anIndex ifAbsent: aBlock
595
+ self subclassResponsibility
743
596
  !
744
597
 
745
- asNumber
746
- <return Number(self)>
598
+ at: anIndex put: anObject
599
+ self subclassResponsibility
747
600
  !
748
601
 
749
- asLowercase
750
- <return self.toLowerCase()>
602
+ atRandom
603
+ ^ self at: self size atRandom
751
604
  !
752
605
 
753
- asUppercase
754
- <return self.toUpperCase()>
606
+ first
607
+ ^self at: 1
755
608
  !
756
609
 
757
- reversed
758
- <return self.split("").reverse().join("")>
610
+ first: n
611
+ "Answer the first n elements of the receiver.
612
+ Raise an error if there are not enough elements."
613
+
614
+ ^ self copyFrom: 1 to: n
759
615
  !
760
616
 
761
- asJavaScriptSelector
762
- ^(self asSelector replace: '^_' with: '') replace: '_.*' with: ''.
617
+ fourth
618
+ ^self at: 4
763
619
  !
764
620
 
765
- asSymbol
766
- ^Symbol lookup: self
621
+ indexOf: anObject
622
+ ^self indexOf: anObject ifAbsent: [self errorNotFound]
767
623
  !
768
624
 
769
- asJSON
770
- ^self
771
- ! !
625
+ indexOf: anObject ifAbsent: aBlock
626
+ <
627
+ for(var i=0;i<self.length;i++){
628
+ if(self[i].__eq(anObject)) {return i+1}
629
+ }
630
+ return aBlock();
631
+ >
632
+ !
772
633
 
773
- !String methodsFor: 'copying'!
634
+ indexOf: anObject startingAt: start
635
+ "Answer the index of the first occurence of anElement after start
636
+ within the receiver. If the receiver does not contain anElement,
637
+ answer 0."
638
+ ^self indexOf: anObject startingAt: start ifAbsent: [0]
639
+ !
774
640
 
775
- , aString
776
- <return self + aString>
641
+ indexOf: anObject startingAt: start ifAbsent: aBlock
642
+ <
643
+ for(var i=start-1;i<self.length;i++){
644
+ if(self[i].__eq(anObject)) {return i+1}
645
+ }
646
+ return aBlock();
647
+ >
777
648
  !
778
649
 
779
- copyFrom: anIndex to: anotherIndex
780
- <return self.substring(anIndex - 1, anotherIndex)>
650
+ last
651
+ ^self at: self size
781
652
  !
782
653
 
783
- shallowCopy
784
- ^self class fromString: self
654
+ second
655
+ ^self at: 2
785
656
  !
786
657
 
787
- deepCopy
788
- ^self shallowCopy
658
+ third
659
+ ^self at: 3
789
660
  ! !
790
661
 
791
- !String methodsFor: 'printing'!
662
+ !SequenceableCollection methodsFor: 'adding'!
792
663
 
793
- printString
794
- ^'''', self, ''''
664
+ addLast: anObject
665
+ self add: anObject
795
666
  !
796
667
 
797
- printNl
798
- <console.log(self)>
668
+ removeLast
669
+ self remove: self last
799
670
  ! !
800
671
 
801
- !String methodsFor: 'regular expressions'!
802
-
803
- replace: aString with: anotherString
804
- ^self replaceRegexp: (RegularExpression fromString: aString flag: 'g') with: anotherString
805
- !
806
-
807
- replaceRegexp: aRegexp with: aString
808
- <return self.replace(aRegexp, aString)>
809
- !
672
+ !SequenceableCollection methodsFor: 'comparing'!
810
673
 
811
- match: aRegexp
812
- <return self.search(aRegexp) !!= -1>
813
- !
674
+ = aCollection
675
+ (self class = aCollection class and: [
676
+ self size = aCollection size]) ifFalse: [^false].
677
+ self withIndexDo: [:each :i |
678
+ (aCollection at: i) = each ifFalse: [^false]].
679
+ ^true
680
+ ! !
814
681
 
815
- trimLeft: separators
682
+ !SequenceableCollection methodsFor: 'converting'!
816
683
 
817
- ^self replaceRegexp: (RegularExpression fromString: '^[', separators, ']+' flag: 'g') with: ''
818
- !
684
+ reversed
685
+ self subclassResponsibility
686
+ ! !
819
687
 
820
- trimRight: separators
688
+ !SequenceableCollection methodsFor: 'copying'!
821
689
 
822
- ^self replaceRegexp: (RegularExpression fromString: '[', separators, ']+$' flag: 'g') with: ''
690
+ copyFrom: anIndex to: anotherIndex
691
+ | range newCollection |
692
+ range := anIndex to: anotherIndex.
693
+ newCollection := self class new: range size.
694
+ range withIndexDo: [:each :i |
695
+ newCollection at: i put: (self at: each)].
696
+ ^newCollection
823
697
  !
824
698
 
825
- trimLeft
826
- ^self trimLeft: '\s'
827
- !
828
-
829
- trimRight
830
- ^self trimRight: '\s'
831
- !
832
-
833
- trimBoth
834
- ^self trimBoth: '\s'
835
- !
836
-
837
- trimBoth: separators
838
-
839
- ^(self trimLeft: separators) trimRight: separators
840
- ! !
841
-
842
- !String methodsFor: 'split join'!
843
-
844
- join: aCollection
845
- ^ String
846
- streamContents: [:stream | aCollection
847
- do: [:each | stream nextPutAll: each asString]
848
- separatedBy: [stream nextPutAll: self]]
849
- !
850
-
851
- lineIndicesDo: aBlock
852
- "execute aBlock with 3 arguments for each line:
853
- - start index of line
854
- - end index of line without line delimiter
855
- - end index of line including line delimiter(s) CR, LF or CRLF"
856
-
857
- | cr lf start sz nextLF nextCR |
858
- start := 1.
859
- sz := self size.
860
- cr := String cr.
861
- nextCR := self indexOf: cr startingAt: 1.
862
- lf := String lf.
863
- nextLF := self indexOf: lf startingAt: 1.
864
- [ start <= sz ] whileTrue: [
865
- (nextLF = 0 and: [ nextCR = 0 ])
866
- ifTrue: [ "No more CR, nor LF, the string is over"
867
- aBlock value: start value: sz value: sz.
868
- ^self ].
869
- (nextCR = 0 or: [ 0 < nextLF and: [ nextLF < nextCR ] ])
870
- ifTrue: [ "Found a LF"
871
- aBlock value: start value: nextLF - 1 value: nextLF.
872
- start := 1 + nextLF.
873
- nextLF := self indexOf: lf startingAt: start ]
874
- ifFalse: [ 1 + nextCR = nextLF
875
- ifTrue: [ "Found a CR-LF pair"
876
- aBlock value: start value: nextCR - 1 value: nextLF.
877
- start := 1 + nextLF.
878
- nextCR := self indexOf: cr startingAt: start.
879
- nextLF := self indexOf: lf startingAt: start ]
880
- ifFalse: [ "Found a CR"
881
- aBlock value: start value: nextCR - 1 value: nextCR.
882
- start := 1 + nextCR.
883
- nextCR := self indexOf: cr startingAt: start ]]]
884
- !
885
-
886
- linesDo: aBlock
887
- "Execute aBlock with each line in this string. The terminating line
888
- delimiters CR, LF or CRLF pairs are not included in what is passed to aBlock"
889
-
890
- self lineIndicesDo: [:start :endWithoutDelimiters :end |
891
- aBlock value: (self copyFrom: start to: endWithoutDelimiters)]
892
- !
893
-
894
- lines
895
- "Answer an array of lines composing this receiver without the line ending delimiters."
896
-
897
- | lines |
898
- lines := Array new.
899
- self linesDo: [:aLine | lines add: aLine].
900
- ^lines
901
- !
902
-
903
- lineNumber: anIndex
904
- "Answer a string containing the characters in the given line number."
905
-
906
- | lineCount |
907
- lineCount := 0.
908
- self lineIndicesDo: [:start :endWithoutDelimiters :end |
909
- (lineCount := lineCount + 1) = anIndex ifTrue: [^self copyFrom: start to: endWithoutDelimiters]].
910
- ^nil
911
- ! !
912
-
913
- !String methodsFor: 'testing'!
914
-
915
- isString
916
- ^true
917
- !
918
-
919
- includesSubString: subString
920
- < return self.indexOf(subString) !!= -1 >
921
- ! !
922
-
923
- !String class methodsFor: 'accessing'!
924
-
925
- streamClass
926
- ^StringStream
927
- !
928
-
929
- cr
930
- <return '\r'>
931
- !
932
-
933
- lf
934
- <return '\n'>
935
- !
936
-
937
- space
938
- <return ' '>
939
- !
940
-
941
- tab
942
- <return '\t'>
943
- !
944
-
945
- crlf
946
- <return '\r\n'>
947
- ! !
948
-
949
- !String class methodsFor: 'instance creation'!
950
-
951
- fromString: aString
952
- <return new self.fn(aString)>
953
- !
954
-
955
- streamContents: blockWithArg
956
- |stream|
957
- stream := (self streamClass on: String new).
958
- blockWithArg value: stream.
959
- ^ stream contents
960
- !
961
-
962
- value: aUTFCharCode
963
-
964
- <return String.fromCharCode(aUTFCharCode);>
965
- ! !
966
-
967
- CharacterArray subclass: #Symbol
968
- instanceVariableNames: ''
969
- category: 'Kernel-Collections'!
970
-
971
- !Symbol methodsFor: 'accessing'!
972
-
973
- at: anIndex ifAbsent: aBlock
974
- ^self asString at: anIndex ifAbsent: aBlock
975
- !
976
-
977
- size
978
- ^self asString size
979
- ! !
980
-
981
- !Symbol methodsFor: 'comparing'!
982
-
983
- < aSymbol
984
- ^self asString < aSymbol asString
985
- !
986
-
987
- <= aSymbol
988
- ^self asString <= aSymbol asString
989
- !
990
-
991
- >= aSymbol
992
- ^self asString >= aSymbol asString
993
- !
994
-
995
- = aSymbol
996
- aSymbol class = self class ifFalse: [^false].
997
- ^self asString = aSymbol asString
998
- !
999
-
1000
- > aSymbol
1001
- ^self asString > aSymbol asString
1002
- ! !
1003
-
1004
- !Symbol methodsFor: 'converting'!
1005
-
1006
- asString
1007
- <return self.value>
1008
- !
1009
-
1010
- asSymbol
1011
- ^self
1012
- !
1013
-
1014
- asJavascript
1015
- ^'smalltalk.symbolFor("', self asString, '")'
1016
- !
1017
-
1018
- asSelector
1019
- ^self asString asSelector
1020
- !
1021
-
1022
- asJSON
1023
- ^self asString asJSON
1024
- ! !
1025
-
1026
- !Symbol methodsFor: 'copying'!
1027
-
1028
- copyFrom: anIndex to: anotherIndex
1029
- ^self class fromString: (self asString copyFrom: anIndex to: anotherIndex)
1030
- !
1031
-
1032
- deepCopy
1033
- ^self
699
+ deepCopy
700
+ | newCollection |
701
+ newCollection := self class new: self size.
702
+ self withIndexDo: [:each :index |
703
+ newCollection at: index put: each deepCopy].
704
+ ^newCollection
1034
705
  !
1035
706
 
1036
707
  shallowCopy
1037
- ^self
708
+ | newCollection |
709
+ newCollection := self class new: self size.
710
+ self withIndexDo: [ :each :index |
711
+ newCollection at: index put: each].
712
+ ^newCollection
1038
713
  ! !
1039
714
 
1040
- !Symbol methodsFor: 'printing'!
1041
-
1042
- printString
1043
- ^'#', self asString
1044
- !
715
+ !SequenceableCollection methodsFor: 'enumerating'!
1045
716
 
1046
- isSymbol
1047
- ^true
717
+ withIndexDo: aBlock
718
+ <for(var i=0;i<self.length;i++){aBlock(self[i], i+1);}>
1048
719
  ! !
1049
720
 
1050
- !Symbol class methodsFor: 'instance creation'!
1051
-
1052
- lookup: aString
1053
- <return smalltalk.symbolFor(aString);>
1054
- !
1055
-
1056
- basicNew
1057
- self shouldNotImplement
1058
- !
721
+ !SequenceableCollection methodsFor: 'printing'!
1059
722
 
1060
- fromString: aString
1061
- ^self lookup: aString
723
+ printString
724
+ | str |
725
+ str := '' writeStream.
726
+ str nextPutAll: super printString, ' ('.
727
+ self
728
+ do: [:each | str nextPutAll: each printString]
729
+ separatedBy: [str nextPutAll: ' '].
730
+ str nextPutAll: ')'.
731
+ ^str contents
1062
732
  ! !
1063
733
 
1064
734
  SequenceableCollection subclass: #Array
1065
735
  instanceVariableNames: ''
1066
- category: 'Kernel-Collections'!
736
+ package: 'Kernel-Collections'!
1067
737
 
1068
738
  !Array methodsFor: 'accessing'!
1069
739
 
1070
- size
1071
- <return self.length>
740
+ at: anIndex ifAbsent: aBlock
741
+ <
742
+ if((anIndex < 1) || (self.length < anIndex)) {return aBlock()};
743
+ return self[anIndex - 1];
744
+ >
1072
745
  !
1073
746
 
1074
747
  at: anIndex put: anObject
1075
748
  <return self[anIndex - 1] = anObject>
1076
749
  !
1077
750
 
1078
- at: anIndex ifAbsent: aBlock
1079
- <
1080
- var value = self[anIndex - 1];
1081
- if(value === undefined) {
1082
- return aBlock();
1083
- } else {
1084
- return value;
1085
- }
1086
- >
751
+ size
752
+ <return self.length>
1087
753
  ! !
1088
754
 
1089
755
  !Array methodsFor: 'adding/removing'!
@@ -1178,540 +844,763 @@ withAll: aCollection
1178
844
  ^instance
1179
845
  ! !
1180
846
 
1181
- SequenceableCollection subclass: #Array
847
+ SequenceableCollection subclass: #CharacterArray
1182
848
  instanceVariableNames: ''
1183
- category: 'Kernel-Collections'!
849
+ package: 'Kernel-Collections'!
1184
850
 
1185
- !Array methodsFor: 'accessing'!
1186
-
1187
- size
1188
- <return self.length>
1189
- !
851
+ !CharacterArray methodsFor: 'accessing'!
1190
852
 
1191
853
  at: anIndex put: anObject
1192
- <return self[anIndex - 1] = anObject>
1193
- !
1194
-
1195
- at: anIndex ifAbsent: aBlock
1196
- <
1197
- var value = self[anIndex - 1];
1198
- if(value === undefined) {
1199
- return aBlock();
1200
- } else {
1201
- return value;
1202
- }
1203
- >
854
+ self errorReadOnly
1204
855
  ! !
1205
856
 
1206
- !Array methodsFor: 'adding/removing'!
857
+ !CharacterArray methodsFor: 'adding'!
1207
858
 
1208
859
  add: anObject
1209
- <self.push(anObject); return anObject;>
860
+ self errorReadOnly
1210
861
  !
1211
862
 
1212
863
  remove: anObject
1213
- <
1214
- for(var i=0;i<self.length;i++) {
1215
- if(self[i] == anObject) {
1216
- self.splice(i,1);
1217
- break;
1218
- }
1219
- }
1220
- >
1221
- !
1222
-
1223
- removeFrom: aNumber to: anotherNumber
1224
- <self.splice(aNumber - 1,anotherNumber - 1)>
864
+ self errorReadOnly
1225
865
  ! !
1226
866
 
1227
- !Array methodsFor: 'converting'!
867
+ !CharacterArray methodsFor: 'converting'!
1228
868
 
1229
- asJavascript
1230
- ^'[', ((self collect: [:each | each asJavascript]) join: ', '), ']'
869
+ asLowercase
870
+ ^self class fromString: self asString asLowercase
1231
871
  !
1232
872
 
1233
- reversed
1234
- <return self._copy().reverse()>
1235
- ! !
1236
-
1237
- !Array methodsFor: 'enumerating'!
1238
-
1239
- join: aString
1240
- <return self.join(aString)>
873
+ asNumber
874
+ ^self asString asNumber
1241
875
  !
1242
876
 
1243
- sort
1244
- ^self basicPerform: 'sort'
877
+ asString
878
+ ^self subclassResponsibility
1245
879
  !
1246
880
 
1247
- sort: aBlock
1248
- <
1249
- return self.sort(function(a, b) {
1250
- if(aBlock(a,b)) {return -1} else {return 1}
1251
- })
1252
- >
881
+ asSymbol
882
+ ^self subclassResponsibility
1253
883
  !
1254
884
 
1255
- sorted
1256
- ^self copy sort
1257
- !
885
+ asUppercase
886
+ ^self class fromString: self asString asUppercase
887
+ ! !
1258
888
 
1259
- sorted: aBlock
1260
- ^self copy sort: aBlock
889
+ !CharacterArray methodsFor: 'copying'!
890
+
891
+ , aString
892
+ ^self asString, aString asString
1261
893
  ! !
1262
894
 
1263
- !Array class methodsFor: 'instance creation'!
895
+ !CharacterArray methodsFor: 'error handling'!
1264
896
 
1265
- new: anInteger
1266
- <return new Array(anInteger)>
1267
- !
897
+ errorReadOnly
898
+ self error: 'Object is read-only'
899
+ ! !
1268
900
 
1269
- with: anObject
1270
- ^(self new: 1)
1271
- at: 1 put: anObject;
1272
- yourself
1273
- !
901
+ !CharacterArray methodsFor: 'printing'!
1274
902
 
1275
- with: anObject with: anObject2
1276
- ^(self new: 2)
1277
- at: 1 put: anObject;
1278
- at: 2 put: anObject2;
1279
- yourself
1280
- !
903
+ printString
904
+ ^self asString printString
905
+ ! !
1281
906
 
1282
- with: anObject with: anObject2 with: anObject3
1283
- ^(self new: 3)
1284
- at: 1 put: anObject;
1285
- at: 2 put: anObject2;
1286
- at: 3 put: anObject3;
1287
- yourself
1288
- !
907
+ !CharacterArray class methodsFor: 'instance creation'!
1289
908
 
1290
- withAll: aCollection
1291
- | instance |
1292
- instance := self new: aCollection size.
1293
- aCollection withIndexDo: [:each :index |
1294
- instance at: index put: each].
1295
- ^instance
909
+ fromString: aString
910
+ self subclassResponsibility
1296
911
  ! !
1297
912
 
1298
- Stream subclass: #StringStream
913
+ CharacterArray subclass: #String
1299
914
  instanceVariableNames: ''
1300
- category: 'Kernel-Collections'!
915
+ package: 'Kernel-Collections'!
1301
916
 
1302
- !StringStream methodsFor: 'reading'!
917
+ !String methodsFor: 'accessing'!
1303
918
 
1304
- next: anInteger
1305
- | tempCollection |
1306
- tempCollection := self collection class new.
1307
- anInteger timesRepeat: [
1308
- self atEnd ifFalse: [
1309
- tempCollection := tempCollection, self next]].
1310
- ^tempCollection
919
+ asciiValue
920
+ <return self.charCodeAt(0);>
921
+ !
922
+
923
+ at: anIndex ifAbsent: aBlock
924
+ <return self[anIndex - 1] || aBlock()>
925
+ !
926
+
927
+ escaped
928
+ <return escape(self)>
929
+ !
930
+
931
+ size
932
+ <return self.length>
933
+ !
934
+
935
+ unescaped
936
+ <return unescape(self)>
1311
937
  ! !
1312
938
 
1313
- !StringStream methodsFor: 'writing'!
939
+ !String methodsFor: 'comparing'!
1314
940
 
1315
- nextPut: aString
1316
- self nextPutAll: aString
941
+ < aString
942
+ <return String(self) < aString._asString()>
1317
943
  !
1318
944
 
1319
- nextPutAll: aString
1320
- self setCollection:
1321
- (self collection copyFrom: 1 to: self position),
1322
- aString,
1323
- (self collection copyFrom: (self position + 1 + aString size) to: self collection size).
1324
- self position: self position + aString size.
1325
- self setStreamSize: (self streamSize max: self position)
945
+ <= aString
946
+ <return String(self) <= aString._asString()>
1326
947
  !
1327
948
 
1328
- cr
1329
- ^self nextPutAll: String cr
949
+ = aString
950
+ aString class = self class ifFalse: [^false].
951
+ <return String(self) === String(aString)>
1330
952
  !
1331
953
 
1332
- crlf
1333
- ^self nextPutAll: String crlf
954
+ == aString
955
+ ^self = aString
1334
956
  !
1335
957
 
1336
- lf
1337
- ^self nextPutAll: String lf
958
+ > aString
959
+ <return String(self) >> aString._asString()>
1338
960
  !
1339
961
 
1340
- space
1341
- self nextPut: ' '
962
+ >= aString
963
+ <return String(self) >>= aString._asString()>
1342
964
  ! !
1343
965
 
1344
- Collection subclass: #Set
1345
- instanceVariableNames: 'elements'
1346
- category: 'Kernel-Collections'!
1347
-
1348
- !Set methodsFor: 'accessing'!
966
+ !String methodsFor: 'converting'!
1349
967
 
1350
- size
1351
- ^elements size
1352
- ! !
968
+ asJSON
969
+ ^self
970
+ !
1353
971
 
1354
- !Set methodsFor: 'adding/removing'!
972
+ asJavaScriptSelector
973
+ ^(self asSelector replace: '^_' with: '') replace: '_.*' with: ''.
974
+ !
1355
975
 
1356
- add: anObject
976
+ asJavascript
1357
977
  <
1358
- var found;
1359
- for(var i=0; i < self['@elements'].length; i++) {
1360
- if(anObject == self['@elements'][i]) {
1361
- found = true;
1362
- break;
1363
- }
1364
- }
1365
- if(!!found) {self['@elements'].push(anObject)}
978
+ if(self.search(/^[a-zA-Z0-9_:.$ ]*$/) == -1)
979
+ return "\"" + self.replace(/[\x00-\x1f"\\\x7f-\x9f]/g, function(ch){var c=ch.charCodeAt(0);return "\\x"+("0"+c.toString(16)).slice(-2)}) + "\"";
980
+ else
981
+ return "\"" + self + "\"";
1366
982
  >
1367
983
  !
1368
984
 
1369
- remove: anObject
1370
- elements remove: anObject
1371
- ! !
985
+ asLowercase
986
+ <return self.toLowerCase()>
987
+ !
1372
988
 
1373
- !Set methodsFor: 'comparing'!
989
+ asNumber
990
+ <return Number(self)>
991
+ !
1374
992
 
1375
- = aCollection
1376
- ^self class = aCollection class and: [
1377
- elements = aCollection asArray]
1378
- ! !
993
+ asSelector
994
+ "If you change this method, change smalltalk.convertSelector too (see js/boot.js file)"
1379
995
 
1380
- !Set methodsFor: 'converting'!
996
+ | selector |
997
+ selector := '_', self.
998
+ selector := selector replace: ':' with: '_'.
999
+ selector := selector replace: '[+]' with: '_plus'.
1000
+ selector := selector replace: '-' with: '_minus'.
1001
+ selector := selector replace: '[*]' with: '_star'.
1002
+ selector := selector replace: '[/]' with: '_slash'.
1003
+ selector := selector replace: '>' with: '_gt'.
1004
+ selector := selector replace: '<' with: '_lt'.
1005
+ selector := selector replace: '=' with: '_eq'.
1006
+ selector := selector replace: ',' with: '_comma'.
1007
+ selector := selector replace: '[@]' with: '_at'.
1008
+ ^selector
1009
+ !
1381
1010
 
1382
- asArray
1383
- ^elements copy
1384
- ! !
1011
+ asString
1012
+ ^self
1013
+ !
1385
1014
 
1386
- !Set methodsFor: 'enumerating'!
1015
+ asSymbol
1016
+ ^Symbol lookup: self
1017
+ !
1387
1018
 
1388
- detect: aBlock ifNone: anotherBlock
1389
- ^elements detect: aBlock ifNone: anotherBlock
1019
+ asUppercase
1020
+ <return self.toUpperCase()>
1390
1021
  !
1391
1022
 
1392
- do: aBlock
1393
- elements do: aBlock
1023
+ reversed
1024
+ <return self.split("").reverse().join("")>
1394
1025
  !
1395
1026
 
1396
- select: aBlock
1397
- | collection |
1398
- collection := self class new.
1399
- self do: [:each |
1400
- (aBlock value: each) ifTrue: [
1401
- collection add: each]].
1402
- ^collection
1027
+ tokenize: aString
1028
+ <return self.split(aString)>
1403
1029
  ! !
1404
1030
 
1405
- !Set methodsFor: 'initialization'!
1031
+ !String methodsFor: 'copying'!
1406
1032
 
1407
- initialize
1408
- super initialize.
1409
- elements := #()
1410
- ! !
1033
+ , aString
1034
+ <return self + aString>
1035
+ !
1411
1036
 
1412
- !Set methodsFor: 'testing'!
1037
+ copyFrom: anIndex to: anotherIndex
1038
+ <return self.substring(anIndex - 1, anotherIndex)>
1039
+ !
1413
1040
 
1414
- includes: anObject
1415
- ^elements includes: anObject
1041
+ deepCopy
1042
+ ^self shallowCopy
1043
+ !
1044
+
1045
+ shallowCopy
1046
+ ^self class fromString: self
1416
1047
  ! !
1417
1048
 
1418
- Collection subclass: #HashedCollection
1419
- instanceVariableNames: ''
1420
- category: 'Kernel-Collections'!
1421
- !HashedCollection commentStamp!
1422
- A HashedCollection is a traditional JavaScript object, or a Smalltalk Dictionary.
1049
+ !String methodsFor: 'printing'!
1423
1050
 
1424
- Unlike a Dictionary, it can only have strings as keys.!
1051
+ printNl
1052
+ <console.log(self)>
1053
+ !
1425
1054
 
1426
- !HashedCollection methodsFor: 'accessing'!
1055
+ printString
1056
+ ^'''', self, ''''
1057
+ ! !
1427
1058
 
1428
- size
1429
- ^self keys size
1059
+ !String methodsFor: 'regular expressions'!
1060
+
1061
+ match: aRegexp
1062
+ <return self.search(aRegexp) !!= -1>
1430
1063
  !
1431
1064
 
1432
- associations
1433
- | associations |
1434
- associations := #().
1435
- self keys do: [:each |
1436
- associations add: (Association key: each value: (self at: each))].
1437
- ^associations
1065
+ matchesOf: aRegularExpression
1066
+ <return self.match(aRegularExpression)>
1438
1067
  !
1439
1068
 
1440
- keys
1441
- <
1442
- var keys = [];
1443
- for(var i in self) {
1444
- if(self.hasOwnProperty(i)) {
1445
- keys.push(i);
1446
- }
1447
- };
1448
- return keys;
1449
- >
1069
+ replace: aString with: anotherString
1070
+ ^self replaceRegexp: (RegularExpression fromString: aString flag: 'g') with: anotherString
1450
1071
  !
1451
1072
 
1452
- values
1453
- ^self keys collect: [:each | self at: each]
1073
+ replaceRegexp: aRegexp with: aString
1074
+ <return self.replace(aRegexp, aString)>
1454
1075
  !
1455
1076
 
1456
- at: aKey put: aValue
1457
- ^self basicAt: aKey put: aValue
1077
+ trimBoth
1078
+ ^self trimBoth: '\s'
1458
1079
  !
1459
1080
 
1460
- at: aKey ifAbsent: aBlock
1461
- ^(self includesKey: aKey)
1462
- ifTrue: [self basicAt: aKey]
1463
- ifFalse: aBlock
1081
+ trimBoth: separators
1082
+
1083
+ ^(self trimLeft: separators) trimRight: separators
1464
1084
  !
1465
1085
 
1466
- at: aKey ifAbsentPut: aBlock
1467
- ^self at: aKey ifAbsent: [
1468
- self at: aKey put: aBlock value]
1086
+ trimLeft
1087
+ ^self trimLeft: '\s'
1469
1088
  !
1470
1089
 
1471
- at: aKey ifPresent: aBlock
1472
- ^(self basicAt: aKey) ifNotNil: [aBlock value: (self at: aKey)]
1090
+ trimLeft: separators
1091
+
1092
+ ^self replaceRegexp: (RegularExpression fromString: '^[', separators, ']+' flag: 'g') with: ''
1473
1093
  !
1474
1094
 
1475
- at: aKey ifPresent: aBlock ifAbsent: anotherBlock
1476
- ^(self basicAt: aKey)
1477
- ifNil: anotherBlock
1478
- ifNotNil: [aBlock value: (self at: aKey)]
1095
+ trimRight
1096
+ ^self trimRight: '\s'
1479
1097
  !
1480
1098
 
1481
- at: aKey
1482
- ^self at: aKey ifAbsent: [self errorNotFound]
1099
+ trimRight: separators
1100
+
1101
+ ^self replaceRegexp: (RegularExpression fromString: '[', separators, ']+$' flag: 'g') with: ''
1483
1102
  ! !
1484
1103
 
1485
- !HashedCollection methodsFor: 'adding/removing'!
1104
+ !String methodsFor: 'split join'!
1486
1105
 
1487
- add: anAssociation
1488
- self at: anAssociation key put: anAssociation value
1106
+ join: aCollection
1107
+ ^ String
1108
+ streamContents: [:stream | aCollection
1109
+ do: [:each | stream nextPutAll: each asString]
1110
+ separatedBy: [stream nextPutAll: self]]
1489
1111
  !
1490
1112
 
1491
- addAll: aHashedCollection
1492
- super addAll: aHashedCollection associations.
1493
- ^aHashedCollection
1113
+ lineIndicesDo: aBlock
1114
+ "execute aBlock with 3 arguments for each line:
1115
+ - start index of line
1116
+ - end index of line without line delimiter
1117
+ - end index of line including line delimiter(s) CR, LF or CRLF"
1118
+
1119
+ | cr lf start sz nextLF nextCR |
1120
+ start := 1.
1121
+ sz := self size.
1122
+ cr := String cr.
1123
+ nextCR := self indexOf: cr startingAt: 1.
1124
+ lf := String lf.
1125
+ nextLF := self indexOf: lf startingAt: 1.
1126
+ [ start <= sz ] whileTrue: [
1127
+ (nextLF = 0 and: [ nextCR = 0 ])
1128
+ ifTrue: [ "No more CR, nor LF, the string is over"
1129
+ aBlock value: start value: sz value: sz.
1130
+ ^self ].
1131
+ (nextCR = 0 or: [ 0 < nextLF and: [ nextLF < nextCR ] ])
1132
+ ifTrue: [ "Found a LF"
1133
+ aBlock value: start value: nextLF - 1 value: nextLF.
1134
+ start := 1 + nextLF.
1135
+ nextLF := self indexOf: lf startingAt: start ]
1136
+ ifFalse: [ 1 + nextCR = nextLF
1137
+ ifTrue: [ "Found a CR-LF pair"
1138
+ aBlock value: start value: nextCR - 1 value: nextLF.
1139
+ start := 1 + nextLF.
1140
+ nextCR := self indexOf: cr startingAt: start.
1141
+ nextLF := self indexOf: lf startingAt: start ]
1142
+ ifFalse: [ "Found a CR"
1143
+ aBlock value: start value: nextCR - 1 value: nextCR.
1144
+ start := 1 + nextCR.
1145
+ nextCR := self indexOf: cr startingAt: start ]]]
1494
1146
  !
1495
1147
 
1496
- removeKey: aKey
1497
- self remove: aKey
1498
- !
1148
+ lineNumber: anIndex
1149
+ "Answer a string containing the characters in the given line number."
1499
1150
 
1500
- remove: aKey ifAbsent: aBlock
1501
- ^self removeKey: aKey ifAbsent: aBlock
1151
+ | lineCount |
1152
+ lineCount := 0.
1153
+ self lineIndicesDo: [:start :endWithoutDelimiters :end |
1154
+ (lineCount := lineCount + 1) = anIndex ifTrue: [^self copyFrom: start to: endWithoutDelimiters]].
1155
+ ^nil
1502
1156
  !
1503
1157
 
1504
- removeKey: aKey ifAbsent: aBlock
1505
- ^(self includesKey: aKey)
1506
- ifFalse: [aBlock value]
1507
- ifTrue: [self basicDelete: aKey]
1508
- ! !
1158
+ lines
1159
+ "Answer an array of lines composing this receiver without the line ending delimiters."
1509
1160
 
1510
- !HashedCollection methodsFor: 'comparing'!
1161
+ | lines |
1162
+ lines := Array new.
1163
+ self linesDo: [:aLine | lines add: aLine].
1164
+ ^lines
1165
+ !
1511
1166
 
1512
- = aHashedCollection
1513
- self class = aHashedCollection class ifFalse: [^false].
1514
- self size = aHashedCollection size ifFalse: [^false].
1515
- ^self associations = aHashedCollection associations
1167
+ linesDo: aBlock
1168
+ "Execute aBlock with each line in this string. The terminating line
1169
+ delimiters CR, LF or CRLF pairs are not included in what is passed to aBlock"
1170
+
1171
+ self lineIndicesDo: [:start :endWithoutDelimiters :end |
1172
+ aBlock value: (self copyFrom: start to: endWithoutDelimiters)]
1516
1173
  ! !
1517
1174
 
1518
- !HashedCollection methodsFor: 'converting'!
1175
+ !String methodsFor: 'testing'!
1519
1176
 
1520
- asDictionary
1521
- ^Dictionary fromPairs: self associations
1177
+ includesSubString: subString
1178
+ < return self.indexOf(subString) !!= -1 >
1522
1179
  !
1523
1180
 
1524
- asJSON
1525
- | c |
1526
- c := self class new.
1527
- self keysAndValuesDo: [:key :value |
1528
- c at: key put: value asJSON].
1529
- ^c
1181
+ isString
1182
+ ^true
1530
1183
  ! !
1531
1184
 
1532
- !HashedCollection methodsFor: 'copying'!
1185
+ !String class methodsFor: 'accessing'!
1533
1186
 
1534
- shallowCopy
1535
- | copy |
1536
- copy := self class new.
1537
- self associationsDo: [:each |
1538
- copy at: each key put: each value].
1539
- ^copy
1187
+ cr
1188
+ <return '\r'>
1540
1189
  !
1541
1190
 
1542
- , aCollection
1543
- self shouldNotImplement
1191
+ crlf
1192
+ <return '\r\n'>
1544
1193
  !
1545
1194
 
1546
- copyFrom: anIndex to: anotherIndex
1547
- self shouldNotImplement
1195
+ lf
1196
+ <return '\n'>
1548
1197
  !
1549
1198
 
1550
- deepCopy
1551
- | copy |
1552
- copy := self class new.
1553
- self associationsDo: [:each |
1554
- copy at: each key put: each value deepCopy].
1555
- ^copy
1556
- ! !
1557
-
1558
- !HashedCollection methodsFor: 'enumerating'!
1559
-
1560
- associationsDo: aBlock
1561
- self associations do: aBlock
1199
+ space
1200
+ <return ' '>
1562
1201
  !
1563
1202
 
1564
- keysAndValuesDo: aBlock
1565
- self associationsDo: [:each |
1566
- aBlock value: each key value: each value]
1203
+ streamClass
1204
+ ^StringStream
1567
1205
  !
1568
1206
 
1569
- do: aBlock
1570
- self values do: aBlock
1571
- !
1207
+ tab
1208
+ <return '\t'>
1209
+ ! !
1572
1210
 
1573
- select: aBlock
1574
- | newDict |
1575
- newDict := self class new.
1576
- self keysAndValuesDo: [:key :value |
1577
- (aBlock value: value) ifTrue: [newDict at: key put: value]].
1578
- ^newDict
1579
- !
1211
+ !String class methodsFor: 'instance creation'!
1580
1212
 
1581
- collect: aBlock
1582
- | newDict |
1583
- newDict := self class new.
1584
- self keysAndValuesDo: [:key :value |
1585
- newDict at: key put: (aBlock value: value)].
1586
- ^newDict
1213
+ fromString: aString
1214
+ <return new self.fn(aString)>
1587
1215
  !
1588
1216
 
1589
- detect: aBlock ifNone: anotherBlock
1590
- ^self values detect: aBlock ifNone: anotherBlock
1217
+ streamContents: blockWithArg
1218
+ |stream|
1219
+ stream := (self streamClass on: String new).
1220
+ blockWithArg value: stream.
1221
+ ^ stream contents
1591
1222
  !
1592
1223
 
1593
- includes: anObject
1594
- ^self values includes: anObject
1595
- ! !
1224
+ value: aUTFCharCode
1596
1225
 
1597
- !HashedCollection methodsFor: 'printing'!
1226
+ <return String.fromCharCode(aUTFCharCode);>
1227
+ ! !
1598
1228
 
1599
- printString
1600
- ^String streamContents: [:aStream|
1601
- aStream
1602
- nextPutAll: super printString;
1603
- nextPutAll: '('.
1604
- self associations
1605
- do: [:anAssociation|
1606
- aStream
1607
- nextPutAll: anAssociation key printString;
1608
- nextPutAll: ' -> ';
1609
- nextPutAll: anAssociation value printString]
1610
- separatedBy: [aStream nextPutAll: ' , '].
1611
- aStream nextPutAll: ')']
1229
+ CharacterArray subclass: #Symbol
1230
+ instanceVariableNames: ''
1231
+ package: 'Kernel-Collections'!
1232
+
1233
+ !Symbol methodsFor: 'accessing'!
1234
+
1235
+ at: anIndex ifAbsent: aBlock
1236
+ ^self asString at: anIndex ifAbsent: aBlock
1612
1237
  !
1613
1238
 
1614
- storeOn: aStream
1615
- aStream nextPutAll: '#{'.
1616
- self associations
1617
- do: [:each | each storeOn: aStream]
1618
- separatedBy: [ aStream nextPutAll: '. '].
1619
- aStream nextPutAll: '}'
1239
+ size
1240
+ ^self asString size
1620
1241
  ! !
1621
1242
 
1622
- !HashedCollection methodsFor: 'testing'!
1243
+ !Symbol methodsFor: 'comparing'!
1623
1244
 
1624
- includesKey: aKey
1625
- <return self.hasOwnProperty(aKey)>
1245
+ < aSymbol
1246
+ ^self asString < aSymbol asString
1247
+ !
1248
+
1249
+ <= aSymbol
1250
+ ^self asString <= aSymbol asString
1251
+ !
1252
+
1253
+ = aSymbol
1254
+ aSymbol class = self class ifFalse: [^false].
1255
+ ^self asString = aSymbol asString
1256
+ !
1257
+
1258
+ > aSymbol
1259
+ ^self asString > aSymbol asString
1260
+ !
1261
+
1262
+ >= aSymbol
1263
+ ^self asString >= aSymbol asString
1626
1264
  ! !
1627
1265
 
1628
- !HashedCollection class methodsFor: 'instance creation'!
1266
+ !Symbol methodsFor: 'converting'!
1629
1267
 
1630
- fromPairs: aCollection
1631
- | dict |
1632
- dict := self new.
1633
- aCollection do: [:each | dict add: each].
1634
- ^dict
1268
+ asJSON
1269
+ ^self asString asJSON
1270
+ !
1271
+
1272
+ asJavascript
1273
+ ^'smalltalk.symbolFor("', self asString, '")'
1274
+ !
1275
+
1276
+ asSelector
1277
+ ^self asString asSelector
1278
+ !
1279
+
1280
+ asString
1281
+ <return self.value>
1282
+ !
1283
+
1284
+ asSymbol
1285
+ ^self
1635
1286
  ! !
1636
1287
 
1637
- HashedCollection subclass: #Dictionary
1638
- instanceVariableNames: 'keys values'
1639
- category: 'Kernel-Collections'!
1288
+ !Symbol methodsFor: 'copying'!
1640
1289
 
1641
- !Dictionary methodsFor: 'accessing'!
1290
+ copyFrom: anIndex to: anotherIndex
1291
+ ^self class fromString: (self asString copyFrom: anIndex to: anotherIndex)
1292
+ !
1642
1293
 
1643
- at: aKey ifAbsent: aBlock
1644
- <
1645
- var index;
1646
- for(var i=0;i<self['@keys'].length;i++){
1647
- if(self['@keys'][i].__eq(aKey)) {index = i;}
1648
- };
1649
- if(typeof index === 'undefined') {
1650
- return aBlock();
1651
- } else {
1652
- return self['@values'][index];
1653
- }
1654
- >
1294
+ deepCopy
1295
+ ^self
1655
1296
  !
1656
1297
 
1657
- keys
1658
- ^keys copy
1298
+ shallowCopy
1299
+ ^self
1300
+ ! !
1301
+
1302
+ !Symbol methodsFor: 'printing'!
1303
+
1304
+ isSymbol
1305
+ ^true
1659
1306
  !
1660
1307
 
1661
- values
1662
- ^values copy
1308
+ printString
1309
+ ^'#', self asString
1310
+ ! !
1311
+
1312
+ !Symbol class methodsFor: 'instance creation'!
1313
+
1314
+ basicNew
1315
+ self shouldNotImplement
1663
1316
  !
1664
1317
 
1665
- at: aKey put: aValue
1666
- <
1667
- var index = self['@keys'].indexOf(aKey);
1668
- if(index === -1) {
1669
- self['@values'].push(aValue);
1670
- self['@keys'].push(aKey);
1671
- } else {
1672
- self['@values'][index] = aValue;
1673
- };
1318
+ fromString: aString
1319
+ ^self lookup: aString
1320
+ !
1674
1321
 
1675
- return aValue;
1676
- >
1322
+ lookup: aString
1323
+ <return smalltalk.symbolFor(aString);>
1677
1324
  ! !
1678
1325
 
1679
- !Dictionary methodsFor: 'adding/removing'!
1326
+ Collection subclass: #Set
1327
+ instanceVariableNames: 'elements'
1328
+ package: 'Kernel-Collections'!
1680
1329
 
1681
- removeKey: aKey ifAbsent: aBlock
1330
+ !Set methodsFor: 'accessing'!
1331
+
1332
+ size
1333
+ ^elements size
1334
+ ! !
1335
+
1336
+ !Set methodsFor: 'adding/removing'!
1337
+
1338
+ add: anObject
1682
1339
  <
1683
- var index = self['@keys'].indexOf(aKey);
1684
- if(index === -1) {
1685
- return aBlock()
1686
- } else {
1687
- self['@keys'].splice(i, 1);
1688
- self['@values'].splice(i, 1);
1689
- return aKey
1690
- };
1340
+ var found;
1341
+ for(var i=0; i < self['@elements'].length; i++) {
1342
+ if(anObject == self['@elements'][i]) {
1343
+ found = true;
1344
+ break;
1345
+ }
1346
+ }
1347
+ if(!!found) {self['@elements'].push(anObject)}
1691
1348
  >
1349
+ !
1350
+
1351
+ remove: anObject
1352
+ elements remove: anObject
1692
1353
  ! !
1693
1354
 
1694
- !Dictionary methodsFor: 'converting'!
1355
+ !Set methodsFor: 'comparing'!
1695
1356
 
1696
- asHashedCollection
1697
- ^HashedCollection fromPairs: self associations
1357
+ = aCollection
1358
+ ^self class = aCollection class and: [
1359
+ elements = aCollection asArray]
1360
+ ! !
1361
+
1362
+ !Set methodsFor: 'converting'!
1363
+
1364
+ asArray
1365
+ ^elements copy
1366
+ ! !
1367
+
1368
+ !Set methodsFor: 'enumerating'!
1369
+
1370
+ detect: aBlock ifNone: anotherBlock
1371
+ ^elements detect: aBlock ifNone: anotherBlock
1698
1372
  !
1699
1373
 
1700
- asJSON
1701
- ^self asHashedCollection asJSON
1374
+ do: aBlock
1375
+ elements do: aBlock
1376
+ !
1377
+
1378
+ select: aBlock
1379
+ | collection |
1380
+ collection := self class new.
1381
+ self do: [:each |
1382
+ (aBlock value: each) ifTrue: [
1383
+ collection add: each]].
1384
+ ^collection
1702
1385
  ! !
1703
1386
 
1704
- !Dictionary methodsFor: 'initialization'!
1387
+ !Set methodsFor: 'initialization'!
1705
1388
 
1706
1389
  initialize
1707
1390
  super initialize.
1708
- keys := #().
1709
- values := #()
1391
+ elements := #()
1710
1392
  ! !
1711
1393
 
1712
- !Dictionary methodsFor: 'testing'!
1394
+ !Set methodsFor: 'testing'!
1713
1395
 
1714
- includesKey: aKey
1715
- ^keys includes: aKey
1396
+ includes: anObject
1397
+ ^elements includes: anObject
1398
+ ! !
1399
+
1400
+ Object subclass: #RegularExpression
1401
+ instanceVariableNames: ''
1402
+ package: 'Kernel-Collections'!
1403
+
1404
+ !RegularExpression methodsFor: 'evaluating'!
1405
+
1406
+ compile: aString
1407
+ <return self.compile(aString)>
1408
+ !
1409
+
1410
+ exec: aString
1411
+ <return self.exec(aString) || nil>
1412
+ !
1413
+
1414
+ test: aString
1415
+ <return self.test(aString)>
1416
+ ! !
1417
+
1418
+ !RegularExpression class methodsFor: 'instance creation'!
1419
+
1420
+ fromString: aString
1421
+ ^self fromString: aString flag: ''
1422
+ !
1423
+
1424
+ fromString: aString flag: anotherString
1425
+ <return new RegExp(aString, anotherString)>
1426
+ ! !
1427
+
1428
+ Object subclass: #Stream
1429
+ instanceVariableNames: 'collection position streamSize'
1430
+ package: 'Kernel-Collections'!
1431
+
1432
+ !Stream methodsFor: 'accessing'!
1433
+
1434
+ collection
1435
+ ^collection
1436
+ !
1437
+
1438
+ contents
1439
+ ^self collection
1440
+ copyFrom: 1
1441
+ to: self streamSize
1442
+ !
1443
+
1444
+ position
1445
+ ^position ifNil: [position := 0]
1446
+ !
1447
+
1448
+ position: anInteger
1449
+ position := anInteger
1450
+ !
1451
+
1452
+ setCollection: aCollection
1453
+ collection := aCollection
1454
+ !
1455
+
1456
+ setStreamSize: anInteger
1457
+ streamSize := anInteger
1458
+ !
1459
+
1460
+ size
1461
+ ^self streamSize
1462
+ !
1463
+
1464
+ streamSize
1465
+ ^streamSize
1466
+ ! !
1467
+
1468
+ !Stream methodsFor: 'actions'!
1469
+
1470
+ close
1471
+ !
1472
+
1473
+ flush
1474
+ !
1475
+
1476
+ reset
1477
+ self position: 0
1478
+ !
1479
+
1480
+ resetContents
1481
+ self reset.
1482
+ self setStreamSize: 0
1483
+ ! !
1484
+
1485
+ !Stream methodsFor: 'enumerating'!
1486
+
1487
+ do: aBlock
1488
+ [self atEnd] whileFalse: [aBlock value: self next]
1489
+ ! !
1490
+
1491
+ !Stream methodsFor: 'positioning'!
1492
+
1493
+ setToEnd
1494
+ self position: self size
1495
+ !
1496
+
1497
+ skip: anInteger
1498
+ self position: ((self position + anInteger) min: self size max: 0)
1499
+ ! !
1500
+
1501
+ !Stream methodsFor: 'reading'!
1502
+
1503
+ next
1504
+ ^self atEnd
1505
+ ifTrue: [nil]
1506
+ ifFalse: [
1507
+ self position: self position + 1.
1508
+ collection at: self position]
1509
+ !
1510
+
1511
+ next: anInteger
1512
+ | tempCollection |
1513
+ tempCollection := self collection class new.
1514
+ anInteger timesRepeat: [
1515
+ self atEnd ifFalse: [
1516
+ tempCollection add: self next]].
1517
+ ^tempCollection
1518
+ !
1519
+
1520
+ peek
1521
+ ^self atEnd ifFalse: [
1522
+ self collection at: self position + 1]
1523
+ ! !
1524
+
1525
+ !Stream methodsFor: 'testing'!
1526
+
1527
+ atEnd
1528
+ ^self position = self size
1529
+ !
1530
+
1531
+ atStart
1532
+ ^self position = 0
1533
+ !
1534
+
1535
+ isEmpty
1536
+ ^self size = 0
1537
+ ! !
1538
+
1539
+ !Stream methodsFor: 'writing'!
1540
+
1541
+ nextPut: anObject
1542
+ self position: self position + 1.
1543
+ self collection at: self position put: anObject.
1544
+ self setStreamSize: (self streamSize max: self position)
1545
+ !
1546
+
1547
+ nextPutAll: aCollection
1548
+ aCollection do: [:each |
1549
+ self nextPut: each]
1550
+ ! !
1551
+
1552
+ !Stream class methodsFor: 'instance creation'!
1553
+
1554
+ on: aCollection
1555
+ ^self new
1556
+ setCollection: aCollection;
1557
+ setStreamSize: aCollection size;
1558
+ yourself
1559
+ ! !
1560
+
1561
+ Stream subclass: #StringStream
1562
+ instanceVariableNames: ''
1563
+ package: 'Kernel-Collections'!
1564
+
1565
+ !StringStream methodsFor: 'reading'!
1566
+
1567
+ next: anInteger
1568
+ | tempCollection |
1569
+ tempCollection := self collection class new.
1570
+ anInteger timesRepeat: [
1571
+ self atEnd ifFalse: [
1572
+ tempCollection := tempCollection, self next]].
1573
+ ^tempCollection
1574
+ ! !
1575
+
1576
+ !StringStream methodsFor: 'writing'!
1577
+
1578
+ cr
1579
+ ^self nextPutAll: String cr
1580
+ !
1581
+
1582
+ crlf
1583
+ ^self nextPutAll: String crlf
1584
+ !
1585
+
1586
+ lf
1587
+ ^self nextPutAll: String lf
1588
+ !
1589
+
1590
+ nextPut: aString
1591
+ self nextPutAll: aString
1592
+ !
1593
+
1594
+ nextPutAll: aString
1595
+ self setCollection:
1596
+ (self collection copyFrom: 1 to: self position),
1597
+ aString,
1598
+ (self collection copyFrom: (self position + 1 + aString size) to: self collection size).
1599
+ self position: self position + aString size.
1600
+ self setStreamSize: (self streamSize max: self position)
1601
+ !
1602
+
1603
+ space
1604
+ self nextPut: ' '
1716
1605
  ! !
1717
1606