resin 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/Kernel-Objects.st
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Smalltalk current createPackage: 'Kernel-Objects' properties: #{}!
|
2
2
|
nil subclass: #Object
|
3
3
|
instanceVariableNames: ''
|
4
|
-
|
4
|
+
package: 'Kernel-Objects'!
|
5
5
|
!Object commentStamp!
|
6
6
|
*Object is the root of the Smalltalk class system*. All classes in the system are subclasses of Object.
|
7
7
|
|
@@ -41,16 +41,30 @@ Objects understand equality `#=` and identity `#==` comparison.
|
|
41
41
|
|
42
42
|
!Object methodsFor: 'accessing'!
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
basicAt: aString
|
45
|
+
<return self[aString]>
|
46
|
+
!
|
47
|
+
|
48
|
+
basicAt: aString put: anObject
|
49
|
+
<return self[aString] = anObject>
|
50
|
+
!
|
51
|
+
|
52
|
+
basicDelete: aString
|
53
|
+
<delete self[aString]; return aString>
|
46
54
|
!
|
47
55
|
|
48
56
|
class
|
49
57
|
<return self.klass>
|
50
58
|
!
|
51
59
|
|
52
|
-
|
53
|
-
|
60
|
+
identityHash
|
61
|
+
<
|
62
|
+
var hash=self.identityHash;
|
63
|
+
if (hash) return hash;
|
64
|
+
hash=smalltalk.nextId();
|
65
|
+
Object.defineProperty(self, 'identityHash', {value:hash});
|
66
|
+
return hash;
|
67
|
+
>
|
54
68
|
!
|
55
69
|
|
56
70
|
instVarAt: aSymbol
|
@@ -65,20 +79,12 @@ instVarAt: aSymbol put: anObject
|
|
65
79
|
<self['@' + varname] = anObject>
|
66
80
|
!
|
67
81
|
|
68
|
-
|
69
|
-
|
70
|
-
!
|
71
|
-
|
72
|
-
basicAt: aString put: anObject
|
73
|
-
<return self[aString] = anObject>
|
74
|
-
!
|
75
|
-
|
76
|
-
basicDelete: aString
|
77
|
-
<delete self[aString]; return aString>
|
82
|
+
size
|
83
|
+
self error: 'Object not indexable'
|
78
84
|
!
|
79
85
|
|
80
|
-
|
81
|
-
|
86
|
+
yourself
|
87
|
+
^self
|
82
88
|
! !
|
83
89
|
|
84
90
|
!Object methodsFor: 'comparing'!
|
@@ -87,14 +93,14 @@ identityHash
|
|
87
93
|
^self == anObject
|
88
94
|
!
|
89
95
|
|
90
|
-
~= anObject
|
91
|
-
^(self = anObject) = false
|
92
|
-
!
|
93
|
-
|
94
96
|
== anObject
|
95
97
|
^self identityHash = anObject identityHash
|
96
98
|
!
|
97
99
|
|
100
|
+
~= anObject
|
101
|
+
^(self = anObject) = false
|
102
|
+
!
|
103
|
+
|
98
104
|
~~ anObject
|
99
105
|
^(self == anObject) = false
|
100
106
|
! !
|
@@ -105,14 +111,6 @@ identityHash
|
|
105
111
|
^Association key: self value: anObject
|
106
112
|
!
|
107
113
|
|
108
|
-
asString
|
109
|
-
^self printString
|
110
|
-
!
|
111
|
-
|
112
|
-
asJavascript
|
113
|
-
^self asString
|
114
|
-
!
|
115
|
-
|
116
114
|
asJSON
|
117
115
|
| variables |
|
118
116
|
variables := HashedCollection new.
|
@@ -123,6 +121,14 @@ asJSON
|
|
123
121
|
|
124
122
|
asJSONString
|
125
123
|
^JSON stringify: self asJSON
|
124
|
+
!
|
125
|
+
|
126
|
+
asJavascript
|
127
|
+
^self asString
|
128
|
+
!
|
129
|
+
|
130
|
+
asString
|
131
|
+
^self printString
|
126
132
|
! !
|
127
133
|
|
128
134
|
!Object methodsFor: 'copying'!
|
@@ -131,50 +137,40 @@ copy
|
|
131
137
|
^self shallowCopy postCopy
|
132
138
|
!
|
133
139
|
|
134
|
-
|
135
|
-
<
|
140
|
+
deepCopy
|
141
|
+
<
|
136
142
|
var copy = self.klass._new();
|
137
143
|
for(var i in self) {
|
138
144
|
if(/^@.+/.test(i)) {
|
139
|
-
copy[i] = self[i];
|
145
|
+
copy[i] = self[i]._deepCopy();
|
140
146
|
}
|
141
147
|
}
|
142
148
|
return copy;
|
143
149
|
>
|
144
150
|
!
|
145
151
|
|
146
|
-
|
147
|
-
|
152
|
+
postCopy
|
153
|
+
!
|
154
|
+
|
155
|
+
shallowCopy
|
156
|
+
<
|
148
157
|
var copy = self.klass._new();
|
149
158
|
for(var i in self) {
|
150
159
|
if(/^@.+/.test(i)) {
|
151
|
-
copy[i] = self[i]
|
160
|
+
copy[i] = self[i];
|
152
161
|
}
|
153
162
|
}
|
154
163
|
return copy;
|
155
164
|
>
|
156
|
-
!
|
157
|
-
|
158
|
-
postCopy
|
159
165
|
! !
|
160
166
|
|
161
167
|
!Object methodsFor: 'error handling'!
|
162
168
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
self error: 'This method is a responsibility of a subclass'
|
169
|
-
!
|
170
|
-
|
171
|
-
shouldNotImplement
|
172
|
-
self error: 'This method should not be implemented in ', self class name
|
173
|
-
!
|
174
|
-
|
175
|
-
try: aBlock catch: anotherBlock
|
176
|
-
<try{result = aBlock()} catch(e) {result = anotherBlock(e)};
|
177
|
-
return result;>
|
169
|
+
deprecatedAPI
|
170
|
+
"Just a simple way to deprecate methods.
|
171
|
+
#deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
|
172
|
+
but it could in the future."
|
173
|
+
console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'
|
178
174
|
!
|
179
175
|
|
180
176
|
doesNotUnderstand: aMessage
|
@@ -184,15 +180,25 @@ doesNotUnderstand: aMessage
|
|
184
180
|
signal
|
185
181
|
!
|
186
182
|
|
183
|
+
error: aString
|
184
|
+
Error signal: aString
|
185
|
+
!
|
186
|
+
|
187
187
|
halt
|
188
188
|
self error: 'Halt encountered'
|
189
189
|
!
|
190
190
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
191
|
+
shouldNotImplement
|
192
|
+
self error: 'This method should not be implemented in ', self class name
|
193
|
+
!
|
194
|
+
|
195
|
+
subclassResponsibility
|
196
|
+
self error: 'This method is a responsibility of a subclass'
|
197
|
+
!
|
198
|
+
|
199
|
+
try: aBlock catch: anotherBlock
|
200
|
+
<try{result = aBlock()} catch(e) {result = anotherBlock(e)};
|
201
|
+
return result;>
|
196
202
|
! !
|
197
203
|
|
198
204
|
!Object methodsFor: 'initialization'!
|
@@ -202,37 +208,43 @@ initialize
|
|
202
208
|
|
203
209
|
!Object methodsFor: 'message handling'!
|
204
210
|
|
205
|
-
perform: aSymbol
|
206
|
-
^self perform: aSymbol withArguments: #()
|
207
|
-
!
|
208
|
-
|
209
|
-
perform: aSymbol withArguments: aCollection
|
210
|
-
^self basicPerform: aSymbol asSelector withArguments: aCollection
|
211
|
-
!
|
212
|
-
|
213
211
|
basicPerform: aSymbol
|
214
212
|
^self basicPerform: aSymbol withArguments: #()
|
215
213
|
!
|
216
214
|
|
217
215
|
basicPerform: aSymbol withArguments: aCollection
|
218
216
|
<return self[aSymbol].apply(self, aCollection);>
|
217
|
+
!
|
218
|
+
|
219
|
+
perform: aSymbol
|
220
|
+
^self perform: aSymbol withArguments: #()
|
221
|
+
!
|
222
|
+
|
223
|
+
perform: aSymbol withArguments: aCollection
|
224
|
+
| selector |
|
225
|
+
selector := aSymbol asSelector.
|
226
|
+
<return smalltalk.send(self, selector, aCollection)>
|
219
227
|
! !
|
220
228
|
|
221
229
|
!Object methodsFor: 'printing'!
|
222
230
|
|
223
|
-
|
224
|
-
|
231
|
+
log: aString block: aBlock
|
232
|
+
|
233
|
+
| result |
|
234
|
+
console log: aString, ' time: ', (Date millisecondsToRun: [result := aBlock value]) printString.
|
235
|
+
^result
|
225
236
|
!
|
226
237
|
|
227
238
|
printNl
|
228
239
|
<console.log(self)>
|
229
240
|
!
|
230
241
|
|
231
|
-
|
242
|
+
printString
|
243
|
+
^'a ', self class name
|
244
|
+
!
|
232
245
|
|
233
|
-
|
234
|
-
|
235
|
-
^result
|
246
|
+
storeOn: aStream
|
247
|
+
aStream nextPutAll: self printString
|
236
248
|
!
|
237
249
|
|
238
250
|
storeString
|
@@ -240,24 +252,10 @@ storeString
|
|
240
252
|
can be reconstructed."
|
241
253
|
|
242
254
|
^ String streamContents: [:s | self storeOn: s]
|
243
|
-
!
|
244
|
-
|
245
|
-
storeOn: aStream
|
246
|
-
aStream nextPutAll: self printString
|
247
255
|
! !
|
248
256
|
|
249
257
|
!Object methodsFor: 'testing'!
|
250
258
|
|
251
|
-
isKindOf: aClass
|
252
|
-
^(self isMemberOf: aClass)
|
253
|
-
ifTrue: [true]
|
254
|
-
ifFalse: [self class inheritsFrom: aClass]
|
255
|
-
!
|
256
|
-
|
257
|
-
isMemberOf: aClass
|
258
|
-
^self class = aClass
|
259
|
-
!
|
260
|
-
|
261
259
|
ifNil: aBlock
|
262
260
|
"inlined in the Compiler"
|
263
261
|
^self
|
@@ -278,27 +276,29 @@ ifNotNil: aBlock ifNil: anotherBlock
|
|
278
276
|
^aBlock value
|
279
277
|
!
|
280
278
|
|
281
|
-
|
279
|
+
isClass
|
282
280
|
^false
|
283
281
|
!
|
284
282
|
|
285
|
-
|
286
|
-
^self
|
283
|
+
isKindOf: aClass
|
284
|
+
^(self isMemberOf: aClass)
|
285
|
+
ifTrue: [true]
|
286
|
+
ifFalse: [self class inheritsFrom: aClass]
|
287
287
|
!
|
288
288
|
|
289
|
-
|
290
|
-
^
|
289
|
+
isMemberOf: aClass
|
290
|
+
^self class = aClass
|
291
291
|
!
|
292
292
|
|
293
293
|
isMetaclass
|
294
294
|
^false
|
295
295
|
!
|
296
296
|
|
297
|
-
|
297
|
+
isNil
|
298
298
|
^false
|
299
299
|
!
|
300
300
|
|
301
|
-
|
301
|
+
isNumber
|
302
302
|
^false
|
303
303
|
!
|
304
304
|
|
@@ -306,8 +306,20 @@ isParseFailure
|
|
306
306
|
^false
|
307
307
|
!
|
308
308
|
|
309
|
+
isString
|
310
|
+
^false
|
311
|
+
!
|
312
|
+
|
309
313
|
isSymbol
|
310
314
|
^false
|
315
|
+
!
|
316
|
+
|
317
|
+
notNil
|
318
|
+
^self isNil not
|
319
|
+
!
|
320
|
+
|
321
|
+
respondsTo: aSelector
|
322
|
+
^self class canUnderstand: aSelector
|
311
323
|
! !
|
312
324
|
|
313
325
|
!Object class methodsFor: 'initialization'!
|
@@ -316,358 +328,383 @@ initialize
|
|
316
328
|
"no op"
|
317
329
|
! !
|
318
330
|
|
319
|
-
Object subclass: #
|
331
|
+
Object subclass: #Boolean
|
320
332
|
instanceVariableNames: ''
|
321
|
-
|
322
|
-
!
|
323
|
-
|
324
|
-
It represents the global JavaScript variable `smalltalk` declared in `js/boot.js`.
|
325
|
-
|
326
|
-
The `smalltalk` object holds all class and packages defined in the system.
|
327
|
-
|
328
|
-
## Classes
|
329
|
-
|
330
|
-
Classes can be accessed using the following methods:
|
331
|
-
|
332
|
-
- `#classes` answers the full list of Smalltalk classes in the system
|
333
|
-
- `#at:` answers a specific class of `nil`
|
334
|
-
|
335
|
-
## Packages
|
333
|
+
package: 'Kernel-Objects'!
|
334
|
+
!Boolean commentStamp!
|
335
|
+
Boolean wraps the JavaScript `Boolean()` constructor. The `true` and `false` objects are the JavaScript boolean objects.
|
336
336
|
|
337
|
-
|
337
|
+
Boolean defines the protocol for logic testing operations and conditional control structures for the logical values.
|
338
|
+
Boolean instances are weither `true` or `false`.!
|
338
339
|
|
339
|
-
|
340
|
-
- `#packageAt:` answers a specific class of `nil`
|
340
|
+
!Boolean methodsFor: 'comparing'!
|
341
341
|
|
342
|
-
|
342
|
+
= aBoolean
|
343
|
+
aBoolean class = self class ifFalse: [^false].
|
344
|
+
<return Boolean(self == true) == aBoolean>
|
345
|
+
!
|
343
346
|
|
344
|
-
|
347
|
+
== aBoolean
|
348
|
+
^self = aBoolean
|
349
|
+
! !
|
345
350
|
|
346
|
-
|
347
|
-
It requires the `Compiler` package and the `js/parser.js` parser file in order to work!
|
351
|
+
!Boolean methodsFor: 'controlling'!
|
348
352
|
|
349
|
-
|
353
|
+
& aBoolean
|
354
|
+
<
|
355
|
+
if(self == true) {
|
356
|
+
return aBoolean;
|
357
|
+
} else {
|
358
|
+
return false;
|
359
|
+
}
|
360
|
+
>
|
361
|
+
!
|
350
362
|
|
351
|
-
|
352
|
-
|
363
|
+
and: aBlock
|
364
|
+
^self = true
|
365
|
+
ifTrue: aBlock
|
366
|
+
ifFalse: [false]
|
353
367
|
!
|
354
368
|
|
355
|
-
|
356
|
-
|
369
|
+
ifFalse: aBlock
|
370
|
+
"inlined in the Compiler"
|
371
|
+
^self ifTrue: [] ifFalse: aBlock
|
357
372
|
!
|
358
373
|
|
359
|
-
|
360
|
-
|
374
|
+
ifFalse: aBlock ifTrue: anotherBlock
|
375
|
+
"inlined in the Compiler"
|
376
|
+
^self ifTrue: anotherBlock ifFalse: aBlock
|
361
377
|
!
|
362
378
|
|
363
|
-
|
364
|
-
|
365
|
-
self
|
366
|
-
^result
|
379
|
+
ifTrue: aBlock
|
380
|
+
"inlined in the Compiler"
|
381
|
+
^self ifTrue: aBlock ifFalse: []
|
367
382
|
!
|
368
383
|
|
369
|
-
|
370
|
-
|
371
|
-
<
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
code := String streamContents: [:s |
|
379
|
-
lines withIndexDo: [:l :i |
|
380
|
-
s nextPutAll: i asString, ': ', l, String lf]].
|
381
|
-
^ Error new messageText: ('Parse error on line ' , row , ' column ' , col , ' : ' , message , ' Below is code with line numbers and ===> marker inserted:' , String lf, code)
|
384
|
+
ifTrue: aBlock ifFalse: anotherBlock
|
385
|
+
"inlined in the Compiler"
|
386
|
+
<
|
387
|
+
if(self == true) {
|
388
|
+
return aBlock();
|
389
|
+
} else {
|
390
|
+
return anotherBlock();
|
391
|
+
}
|
392
|
+
>
|
382
393
|
!
|
383
394
|
|
384
|
-
|
385
|
-
|
386
|
-
<return self.reservedWords>
|
395
|
+
not
|
396
|
+
^self = false
|
387
397
|
!
|
388
398
|
|
389
|
-
|
390
|
-
|
399
|
+
or: aBlock
|
400
|
+
^self = true
|
401
|
+
ifTrue: [true]
|
402
|
+
ifFalse: aBlock
|
391
403
|
!
|
392
404
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
405
|
+
| aBoolean
|
406
|
+
<
|
407
|
+
if(self == true) {
|
408
|
+
return true;
|
409
|
+
} else {
|
410
|
+
return aBoolean;
|
411
|
+
}
|
412
|
+
>
|
397
413
|
! !
|
398
414
|
|
399
|
-
!
|
415
|
+
!Boolean methodsFor: 'converting'!
|
400
416
|
|
401
|
-
|
402
|
-
|
403
|
-
aClass methodDictionary values do: [:each |
|
404
|
-
aClass removeCompiledMethod: each].
|
405
|
-
aClass class methodDictionary values do: [:each |
|
406
|
-
aClass class removeCompiledMethod: each].
|
407
|
-
self basicDelete: aClass name
|
417
|
+
asJSON
|
418
|
+
^self
|
408
419
|
! !
|
409
420
|
|
410
|
-
!
|
411
|
-
|
412
|
-
packages
|
413
|
-
"Return all Package instances in the system."
|
414
|
-
|
415
|
-
<return self.packages.all()>
|
416
|
-
!
|
417
|
-
|
418
|
-
packageAt: packageName
|
419
|
-
<return self.packages[packageName]>
|
420
|
-
!
|
421
|
+
!Boolean methodsFor: 'copying'!
|
421
422
|
|
422
|
-
|
423
|
-
|
423
|
+
deepCopy
|
424
|
+
^self
|
424
425
|
!
|
425
426
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
| pkg |
|
430
|
-
pkg := self packageAt: packageName ifAbsent: [self error: 'Missing package: ', packageName].
|
431
|
-
pkg classes do: [:each |
|
432
|
-
self removeClass: each].
|
433
|
-
self deletePackage: packageName
|
434
|
-
!
|
427
|
+
shallowCopy
|
428
|
+
^self
|
429
|
+
! !
|
435
430
|
|
436
|
-
|
437
|
-
"Rename a package."
|
431
|
+
!Boolean methodsFor: 'printing'!
|
438
432
|
|
439
|
-
|
440
|
-
|
441
|
-
(self packageAt: newName) ifNotNil: [self error: 'Already exists a package called: ', newName].
|
442
|
-
<smalltalk.packages[newName] = smalltalk.packages[packageName]>.
|
443
|
-
pkg name: newName.
|
444
|
-
self deletePackage: packageName.
|
433
|
+
printString
|
434
|
+
<return self.toString()>
|
445
435
|
! !
|
446
436
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
437
|
+
Object subclass: #Date
|
438
|
+
instanceVariableNames: ''
|
439
|
+
package: 'Kernel-Objects'!
|
440
|
+
!Date commentStamp!
|
441
|
+
The Date class is used to work with dates and times. Therefore `Date today` and `Date now` are both valid in
|
442
|
+
Amber and answer the same date object.
|
451
443
|
|
452
|
-
|
453
|
-
!
|
444
|
+
Date wraps the `Date()` JavaScript constructor, and Smalltalk date objects are JavaScript date objects.!
|
454
445
|
|
455
|
-
|
456
|
-
"Deletes a package by deleting its binding, but does not check if it contains classes etc.
|
457
|
-
To remove a package, use #removePackage instead."
|
446
|
+
!Date methodsFor: 'accessing'!
|
458
447
|
|
459
|
-
|
448
|
+
day
|
449
|
+
^self dayOfWeek
|
460
450
|
!
|
461
451
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
| object |
|
466
|
-
<object = {};>.
|
467
|
-
aDict keysAndValuesDo: [:key :value |
|
468
|
-
<object[key] = value>.
|
469
|
-
].
|
470
|
-
<return smalltalk.addPackage(packageName, object)>
|
471
|
-
! !
|
472
|
-
|
473
|
-
Smalltalk class instanceVariableNames: 'current'!
|
474
|
-
|
475
|
-
!Smalltalk class methodsFor: 'accessing'!
|
476
|
-
|
477
|
-
current
|
478
|
-
<return smalltalk>
|
479
|
-
! !
|
480
|
-
|
481
|
-
Object subclass: #Package
|
482
|
-
instanceVariableNames: 'commitPathJs commitPathSt'
|
483
|
-
category: 'Kernel-Objects'!
|
484
|
-
!Package commentStamp!
|
485
|
-
A Package is similar to a "class category" typically found in other Smalltalks like Pharo or Squeak. Amber does not have class categories anymore, it had in the beginning but now each class in the system knows which package it belongs to.
|
452
|
+
day: aNumber
|
453
|
+
self dayOfWeek: aNumber
|
454
|
+
!
|
486
455
|
|
487
|
-
|
488
|
-
|
456
|
+
dayOfMonth
|
457
|
+
<return self.getDate()>
|
458
|
+
!
|
489
459
|
|
490
|
-
|
460
|
+
dayOfMonth: aNumber
|
461
|
+
<self.setDate(aNumber)>
|
462
|
+
!
|
491
463
|
|
492
|
-
|
464
|
+
dayOfWeek
|
465
|
+
<return self.getDay() + 1>
|
466
|
+
!
|
493
467
|
|
494
|
-
|
468
|
+
dayOfWeek: aNumber
|
469
|
+
<return self.setDay(aNumber - 1)>
|
470
|
+
!
|
495
471
|
|
496
|
-
|
497
|
-
|
498
|
-
|
472
|
+
hours
|
473
|
+
<return self.getHours()>
|
474
|
+
!
|
499
475
|
|
500
|
-
|
476
|
+
hours: aNumber
|
477
|
+
<self.setHours(aNumber)>
|
478
|
+
!
|
501
479
|
|
502
|
-
|
480
|
+
milliseconds
|
481
|
+
<return self.getMilliseconds()>
|
482
|
+
!
|
503
483
|
|
504
|
-
|
484
|
+
milliseconds: aNumber
|
485
|
+
<self.setMilliseconds(aNumber)>
|
486
|
+
!
|
505
487
|
|
506
|
-
|
507
|
-
<return self.
|
488
|
+
minutes
|
489
|
+
<return self.getMinutes()>
|
508
490
|
!
|
509
491
|
|
510
|
-
|
511
|
-
<self.
|
492
|
+
minutes: aNumber
|
493
|
+
<self.setMinutes(aNumber)>
|
512
494
|
!
|
513
495
|
|
514
|
-
|
515
|
-
|
496
|
+
month
|
497
|
+
<return self.getMonth() + 1>
|
516
498
|
!
|
517
499
|
|
518
|
-
|
519
|
-
|
500
|
+
month: aNumber
|
501
|
+
<self.setMonth(aNumber - 1)>
|
520
502
|
!
|
521
503
|
|
522
|
-
|
523
|
-
|
504
|
+
seconds
|
505
|
+
<return self.getSeconds()>
|
524
506
|
!
|
525
507
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
| object |
|
530
|
-
<object = {};>.
|
531
|
-
aDict keysAndValuesDo: [:key :value |
|
532
|
-
<object[key] = value>.
|
533
|
-
].
|
534
|
-
<return self.properties = object>
|
508
|
+
seconds: aNumber
|
509
|
+
<self.setSeconds(aNumber)>
|
535
510
|
!
|
536
511
|
|
537
|
-
|
538
|
-
|
512
|
+
time
|
513
|
+
<return self.getTime()>
|
539
514
|
!
|
540
515
|
|
541
|
-
|
542
|
-
|
516
|
+
time: aNumber
|
517
|
+
<self.setTime(aNumber)>
|
543
518
|
!
|
544
519
|
|
545
|
-
|
546
|
-
|
520
|
+
year
|
521
|
+
<return self.getFullYear()>
|
547
522
|
!
|
548
523
|
|
549
|
-
|
550
|
-
|
524
|
+
year: aNumber
|
525
|
+
<self.setFullYear(aNumber)>
|
551
526
|
! !
|
552
527
|
|
553
|
-
!
|
528
|
+
!Date methodsFor: 'arithmetic'!
|
554
529
|
|
555
|
-
|
556
|
-
|
557
|
-
^Smalltalk current classes select: [:c | c package == self]
|
530
|
+
+ aDate
|
531
|
+
<return self + aDate>
|
558
532
|
!
|
559
533
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
^self classes inject: #() into: [:acc :each |
|
564
|
-
acc isEmpty
|
565
|
-
ifTrue: [acc add: each; yourself]
|
566
|
-
ifFalse: [(acc includes: each superclass)
|
567
|
-
ifTrue: [acc add: each; yourself]
|
568
|
-
ifFalse: [{each}, acc]]]
|
534
|
+
- aDate
|
535
|
+
<return self - aDate>
|
569
536
|
! !
|
570
537
|
|
571
|
-
!
|
572
|
-
|
573
|
-
printString
|
574
|
-
^self name
|
575
|
-
! !
|
538
|
+
!Date methodsFor: 'comparing'!
|
576
539
|
|
577
|
-
|
540
|
+
< aDate
|
541
|
+
<return self < aDate>
|
542
|
+
!
|
578
543
|
|
579
|
-
|
580
|
-
<return
|
544
|
+
<= aDate
|
545
|
+
<return self <= aDate>
|
581
546
|
!
|
582
547
|
|
583
|
-
|
584
|
-
<return self
|
548
|
+
> aDate
|
549
|
+
<return self >> aDate>
|
585
550
|
!
|
586
551
|
|
587
|
-
|
588
|
-
<return self
|
552
|
+
>= aDate
|
553
|
+
<return self >>= aDate>
|
589
554
|
! !
|
590
555
|
|
591
|
-
!
|
556
|
+
!Date methodsFor: 'converting'!
|
592
557
|
|
593
|
-
|
558
|
+
asDateString
|
559
|
+
<return self.toDateString()>
|
560
|
+
!
|
594
561
|
|
595
|
-
|
562
|
+
asLocaleString
|
563
|
+
<return self.toLocaleString()>
|
596
564
|
!
|
597
565
|
|
598
|
-
|
566
|
+
asMilliseconds
|
567
|
+
^self time
|
568
|
+
!
|
599
569
|
|
600
|
-
|
570
|
+
asNumber
|
571
|
+
^self asMilliseconds
|
601
572
|
!
|
602
573
|
|
603
|
-
|
574
|
+
asString
|
575
|
+
<return self.toString()>
|
576
|
+
!
|
604
577
|
|
605
|
-
|
578
|
+
asTimeString
|
579
|
+
<return self.toTimeString()>
|
606
580
|
! !
|
607
581
|
|
608
|
-
|
582
|
+
!Date methodsFor: 'printing'!
|
609
583
|
|
610
|
-
|
584
|
+
printString
|
585
|
+
^self asString
|
586
|
+
! !
|
611
587
|
|
612
|
-
|
613
|
-
|
588
|
+
!Date class methodsFor: 'instance creation'!
|
589
|
+
|
590
|
+
fromMilliseconds: aNumber
|
591
|
+
^self new: aNumber
|
614
592
|
!
|
615
593
|
|
616
|
-
|
617
|
-
|
594
|
+
fromSeconds: aNumber
|
595
|
+
^self fromMilliseconds: aNumber * 1000
|
618
596
|
!
|
619
597
|
|
620
|
-
|
621
|
-
|
598
|
+
fromString: aString
|
599
|
+
"Example: Date fromString('2011/04/15 00:00:00')"
|
600
|
+
^self new: aString
|
622
601
|
!
|
623
602
|
|
624
|
-
|
625
|
-
|
603
|
+
millisecondsToRun: aBlock
|
604
|
+
| t |
|
605
|
+
t := Date now.
|
606
|
+
aBlock value.
|
607
|
+
^Date now - t
|
626
608
|
!
|
627
609
|
|
628
|
-
|
629
|
-
|
630
|
-
|
610
|
+
new: anObject
|
611
|
+
<return new Date(anObject)>
|
612
|
+
!
|
613
|
+
|
614
|
+
now
|
615
|
+
^self today
|
616
|
+
!
|
617
|
+
|
618
|
+
today
|
619
|
+
^self new
|
631
620
|
! !
|
632
621
|
|
633
|
-
|
622
|
+
Object subclass: #JSObjectProxy
|
623
|
+
instanceVariableNames: 'jsObject'
|
624
|
+
package: 'Kernel-Objects'!
|
625
|
+
!JSObjectProxy commentStamp!
|
626
|
+
JSObjectProxy handles sending messages to JavaScript object, therefore accessing JavaScript objects from Amber is transparent.
|
627
|
+
JSOjbectProxy makes intensive use of `#doesNotUnderstand:`.
|
634
628
|
|
635
|
-
|
636
|
-
|
629
|
+
## Examples
|
630
|
+
|
631
|
+
JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
|
632
|
+
|
633
|
+
window alert: 'hello world'.
|
634
|
+
window inspect.
|
635
|
+
(window jQuery: 'body') append: 'hello world'
|
636
|
+
|
637
|
+
Smalltalk messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.
|
638
|
+
|
639
|
+
## Message conversion rules
|
640
|
+
|
641
|
+
- `someUser name` becomes `someUser.name`
|
642
|
+
- `someUser name: 'John'` becomes `someUser name = "John"`
|
643
|
+
- `console log: 'hello world'` becomes `console.log('hello world')`
|
644
|
+
- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
|
645
|
+
|
646
|
+
__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
|
647
|
+
|
648
|
+
!JSObjectProxy methodsFor: 'accessing'!
|
649
|
+
|
650
|
+
at: aSymbol
|
651
|
+
| attr |
|
652
|
+
attr := aSymbol asString.
|
653
|
+
<return self['@jsObject'][attr]>
|
637
654
|
!
|
638
655
|
|
639
|
-
|
640
|
-
|
656
|
+
at: aSymbol put: anObject
|
657
|
+
| attr |
|
658
|
+
attr := aSymbol asString.
|
659
|
+
<self['@jsObject'][attr] = anObject>
|
641
660
|
!
|
642
661
|
|
643
|
-
|
644
|
-
|
645
|
-
key := 'smalltalk.packages.' , aPackageName.
|
646
|
-
sourceCode := Exporter new exportPackage: aPackageName.
|
647
|
-
<localStorage[key] = escape(sourceCode)>
|
662
|
+
jsObject
|
663
|
+
^jsObject
|
648
664
|
!
|
649
665
|
|
650
|
-
|
651
|
-
|
652
|
-
do: [ :each | <smalltalk.init(each)> ];
|
653
|
-
do: [ :each | each initialize ]
|
666
|
+
jsObject: aJSObject
|
667
|
+
jsObject := aJSObject
|
654
668
|
! !
|
655
669
|
|
656
|
-
!
|
670
|
+
!JSObjectProxy methodsFor: 'proxy'!
|
657
671
|
|
658
|
-
|
672
|
+
doesNotUnderstand: aMessage
|
673
|
+
| obj selector jsSelector arguments |
|
674
|
+
obj := self jsObject.
|
675
|
+
selector := aMessage selector.
|
676
|
+
jsSelector := selector asJavaScriptSelector.
|
677
|
+
arguments := aMessage arguments.
|
678
|
+
<if(obj[jsSelector] !!= undefined) {return smalltalk.send(obj, jsSelector, arguments)}>.
|
679
|
+
super doesNotUnderstand: aMessage
|
680
|
+
!
|
659
681
|
|
660
|
-
|
682
|
+
inspectOn: anInspector
|
683
|
+
| variables |
|
684
|
+
variables := Dictionary new.
|
685
|
+
variables at: '#self' put: self jsObject.
|
686
|
+
anInspector setLabel: self printString.
|
687
|
+
<for(var i in self['@jsObject']) {
|
688
|
+
variables._at_put_(i, self['@jsObject'][i]);
|
689
|
+
}>.
|
690
|
+
anInspector setVariables: variables
|
661
691
|
!
|
662
692
|
|
663
|
-
|
693
|
+
printString
|
694
|
+
^self jsObject toString
|
695
|
+
! !
|
664
696
|
|
665
|
-
|
697
|
+
!JSObjectProxy class methodsFor: 'instance creation'!
|
698
|
+
|
699
|
+
on: aJSObject
|
700
|
+
^self new
|
701
|
+
jsObject: aJSObject;
|
702
|
+
yourself
|
666
703
|
! !
|
667
704
|
|
668
705
|
Object subclass: #Number
|
669
706
|
instanceVariableNames: ''
|
670
|
-
|
707
|
+
package: 'Kernel-Objects'!
|
671
708
|
!Number commentStamp!
|
672
709
|
Number holds the most general methods for dealing with numbers.
|
673
710
|
Number is directly mapped to JavaScript Number.
|
@@ -691,6 +728,11 @@ identityHash
|
|
691
728
|
|
692
729
|
!Number methodsFor: 'arithmetic'!
|
693
730
|
|
731
|
+
* aNumber
|
732
|
+
"Inlined in the Compiler"
|
733
|
+
<return self * aNumber>
|
734
|
+
!
|
735
|
+
|
694
736
|
+ aNumber
|
695
737
|
"Inlined in the Compiler"
|
696
738
|
<return self + aNumber>
|
@@ -701,879 +743,447 @@ identityHash
|
|
701
743
|
<return self - aNumber>
|
702
744
|
!
|
703
745
|
|
704
|
-
* aNumber
|
705
|
-
"Inlined in the Compiler"
|
706
|
-
<return self * aNumber>
|
707
|
-
!
|
708
|
-
|
709
746
|
/ aNumber
|
710
747
|
"Inlined in the Compiler"
|
711
748
|
<return self / aNumber>
|
712
749
|
!
|
713
750
|
|
714
|
-
max: aNumber
|
715
|
-
<return Math.max(self, aNumber);>
|
716
|
-
!
|
717
|
-
|
718
|
-
min: aNumber
|
719
|
-
<return Math.min(self, aNumber);>
|
720
|
-
!
|
721
|
-
|
722
|
-
negated
|
723
|
-
^0 - self
|
724
|
-
!
|
725
|
-
|
726
751
|
\\ aNumber
|
727
752
|
<return self % aNumber>
|
728
753
|
!
|
729
754
|
|
730
|
-
|
731
|
-
<return Math.
|
732
|
-
!
|
733
|
-
|
734
|
-
squared
|
735
|
-
^self * self
|
736
|
-
! !
|
737
|
-
|
738
|
-
!Number methodsFor: 'comparing'!
|
739
|
-
|
740
|
-
= aNumber
|
741
|
-
aNumber isNumber ifFalse: [^false].
|
742
|
-
<return Number(self) == aNumber>
|
743
|
-
!
|
744
|
-
|
745
|
-
> aNumber
|
746
|
-
"Inlined in the Compiler"
|
747
|
-
<return self >> aNumber>
|
748
|
-
!
|
749
|
-
|
750
|
-
< aNumber
|
751
|
-
"Inlined in the Compiler"
|
752
|
-
<return self < aNumber>
|
753
|
-
!
|
754
|
-
|
755
|
-
>= aNumber
|
756
|
-
"Inlined in the Compiler"
|
757
|
-
<return self >>= aNumber>
|
758
|
-
!
|
759
|
-
|
760
|
-
<= aNumber
|
761
|
-
"Inlined in the Compiler"
|
762
|
-
<return self <= aNumber>
|
763
|
-
! !
|
764
|
-
|
765
|
-
!Number methodsFor: 'converting'!
|
766
|
-
|
767
|
-
rounded
|
768
|
-
<return Math.round(self);>
|
769
|
-
!
|
770
|
-
|
771
|
-
truncated
|
772
|
-
|result|
|
773
|
-
|
774
|
-
self >= 0
|
775
|
-
ifTrue: [<result = Math.floor(self);>]
|
776
|
-
ifFalse: [<result = (Math.floor(self * (-1)) * (-1));>].
|
777
|
-
|
778
|
-
^ result
|
779
|
-
!
|
780
|
-
|
781
|
-
to: aNumber
|
782
|
-
| array first last count |
|
783
|
-
first := self truncated.
|
784
|
-
last := aNumber truncated + 1.
|
785
|
-
count := 1.
|
786
|
-
array := Array new.
|
787
|
-
(last - first) timesRepeat: [
|
788
|
-
array at: count put: first.
|
789
|
-
count := count + 1.
|
790
|
-
first := first + 1].
|
791
|
-
^array
|
792
|
-
!
|
793
|
-
|
794
|
-
asString
|
795
|
-
^self printString
|
796
|
-
!
|
797
|
-
|
798
|
-
asJavascript
|
799
|
-
^'(', self printString, ')'
|
800
|
-
!
|
801
|
-
|
802
|
-
atRandom
|
803
|
-
^(Random new next * self) truncated + 1
|
804
|
-
!
|
805
|
-
|
806
|
-
@ aNumber
|
807
|
-
^Point x: self y: aNumber
|
755
|
+
max: aNumber
|
756
|
+
<return Math.max(self, aNumber);>
|
808
757
|
!
|
809
758
|
|
810
|
-
|
811
|
-
|
759
|
+
min: aNumber
|
760
|
+
<return Math.min(self, aNumber);>
|
812
761
|
!
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
value := self.
|
817
|
-
array := Array new.
|
818
|
-
pos := 1.
|
819
|
-
step = 0 ifTrue: [self error: 'step must be non-zero'].
|
820
|
-
step < 0
|
821
|
-
ifTrue: [[ value >= stop ] whileTrue: [
|
822
|
-
array at: pos put: value.
|
823
|
-
pos := pos + 1.
|
824
|
-
value := value + step]]
|
825
|
-
ifFalse: [[ value <= stop ] whileTrue: [
|
826
|
-
array at: pos put: value.
|
827
|
-
pos := pos + 1.
|
828
|
-
value := value + step]].
|
829
|
-
^array
|
830
|
-
!
|
831
|
-
|
832
|
-
asJSON
|
833
|
-
^self
|
834
|
-
! !
|
835
|
-
|
836
|
-
!Number methodsFor: 'copying'!
|
837
|
-
|
838
|
-
deepCopy
|
839
|
-
^self copy
|
840
|
-
!
|
841
|
-
|
842
|
-
copy
|
843
|
-
^self
|
844
|
-
! !
|
845
|
-
|
846
|
-
!Number methodsFor: 'enumerating'!
|
847
|
-
|
848
|
-
timesRepeat: aBlock
|
849
|
-
| integer count |
|
850
|
-
integer := self truncated.
|
851
|
-
count := 1.
|
852
|
-
[count > self] whileFalse: [
|
853
|
-
aBlock value.
|
854
|
-
count := count + 1]
|
855
|
-
!
|
856
|
-
|
857
|
-
to: stop do: aBlock
|
858
|
-
"Evaluate aBlock for each number from self to aNumber."
|
859
|
-
| nextValue |
|
860
|
-
nextValue := self.
|
861
|
-
[nextValue <= stop]
|
862
|
-
whileTrue:
|
863
|
-
[aBlock value: nextValue.
|
864
|
-
nextValue := nextValue + 1]
|
865
|
-
!
|
866
|
-
|
867
|
-
to: stop by: step do: aBlock
|
868
|
-
| value |
|
869
|
-
value := self.
|
870
|
-
step = 0 ifTrue: [self error: 'step must be non-zero'].
|
871
|
-
step < 0
|
872
|
-
ifTrue: [[ value >= stop ] whileTrue: [
|
873
|
-
aBlock value: value.
|
874
|
-
value := value + step]]
|
875
|
-
ifFalse: [[ value <= stop ] whileTrue: [
|
876
|
-
aBlock value: value.
|
877
|
-
value := value + step]]
|
878
|
-
! !
|
879
|
-
|
880
|
-
!Number methodsFor: 'printing'!
|
881
|
-
|
882
|
-
printString
|
883
|
-
<return String(self)>
|
884
|
-
!
|
885
|
-
|
886
|
-
printShowingDecimalPlaces: placesDesired
|
887
|
-
<return self.toFixed(placesDesired)>
|
888
|
-
! !
|
889
|
-
|
890
|
-
!Number methodsFor: 'testing'!
|
891
|
-
|
892
|
-
isNumber
|
893
|
-
^true
|
894
|
-
!
|
895
|
-
|
896
|
-
even
|
897
|
-
^ 0 = (self \\ 2)
|
898
|
-
!
|
899
|
-
|
900
|
-
odd
|
901
|
-
^ self even not
|
902
|
-
!
|
903
|
-
|
904
|
-
negative
|
905
|
-
"Answer whether the receiver is mathematically negative."
|
906
|
-
|
907
|
-
^ self < 0
|
908
|
-
!
|
909
|
-
|
910
|
-
positive
|
911
|
-
"Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
|
912
|
-
|
913
|
-
^ self >= 0
|
914
|
-
!
|
915
|
-
|
916
|
-
isZero
|
917
|
-
^self = 0
|
918
|
-
! !
|
919
|
-
|
920
|
-
!Number methodsFor: 'timeouts/intervals'!
|
921
|
-
|
922
|
-
clearInterval
|
923
|
-
<clearInterval(Number(self))>
|
924
|
-
!
|
925
|
-
|
926
|
-
clearTimeout
|
927
|
-
<clearTimeout(Number(self))>
|
928
|
-
! !
|
929
|
-
|
930
|
-
!Number class methodsFor: 'instance creation'!
|
931
|
-
|
932
|
-
pi
|
933
|
-
<return Math.PI>
|
934
|
-
! !
|
935
|
-
|
936
|
-
Object subclass: #Boolean
|
937
|
-
instanceVariableNames: ''
|
938
|
-
category: 'Kernel-Objects'!
|
939
|
-
!Boolean commentStamp!
|
940
|
-
Boolean wraps the JavaScript `Boolean()` constructor. The `true` and `false` objects are the JavaScript boolean objects.
|
941
|
-
|
942
|
-
Boolean defines the protocol for logic testing operations and conditional control structures for the logical values.
|
943
|
-
Boolean instances are weither `true` or `false`.!
|
944
|
-
|
945
|
-
!Boolean methodsFor: 'comparing'!
|
946
|
-
|
947
|
-
= aBoolean
|
948
|
-
aBoolean class = self class ifFalse: [^false].
|
949
|
-
<return Boolean(self == true) == aBoolean>
|
950
|
-
! !
|
951
|
-
|
952
|
-
!Boolean methodsFor: 'controlling'!
|
953
|
-
|
954
|
-
ifTrue: aBlock
|
955
|
-
"inlined in the Compiler"
|
956
|
-
^self ifTrue: aBlock ifFalse: []
|
957
|
-
!
|
958
|
-
|
959
|
-
ifFalse: aBlock
|
960
|
-
"inlined in the Compiler"
|
961
|
-
^self ifTrue: [] ifFalse: aBlock
|
962
|
-
!
|
963
|
-
|
964
|
-
ifFalse: aBlock ifTrue: anotherBlock
|
965
|
-
"inlined in the Compiler"
|
966
|
-
^self ifTrue: anotherBlock ifFalse: aBlock
|
967
|
-
!
|
968
|
-
|
969
|
-
ifTrue: aBlock ifFalse: anotherBlock
|
970
|
-
"inlined in the Compiler"
|
971
|
-
<
|
972
|
-
if(self == true) {
|
973
|
-
return aBlock();
|
974
|
-
} else {
|
975
|
-
return anotherBlock();
|
976
|
-
}
|
977
|
-
>
|
978
|
-
!
|
979
|
-
|
980
|
-
and: aBlock
|
981
|
-
^self = true
|
982
|
-
ifTrue: aBlock
|
983
|
-
ifFalse: [false]
|
984
|
-
!
|
985
|
-
|
986
|
-
or: aBlock
|
987
|
-
^self = true
|
988
|
-
ifTrue: [true]
|
989
|
-
ifFalse: aBlock
|
990
|
-
!
|
991
|
-
|
992
|
-
not
|
993
|
-
^self = false
|
994
|
-
!
|
995
|
-
|
996
|
-
& aBoolean
|
997
|
-
<
|
998
|
-
if(self == true) {
|
999
|
-
return aBoolean;
|
1000
|
-
} else {
|
1001
|
-
return false;
|
1002
|
-
}
|
1003
|
-
>
|
1004
|
-
!
|
1005
|
-
|
1006
|
-
| aBoolean
|
1007
|
-
<
|
1008
|
-
if(self == true) {
|
1009
|
-
return true;
|
1010
|
-
} else {
|
1011
|
-
return aBoolean;
|
1012
|
-
}
|
1013
|
-
>
|
1014
|
-
! !
|
1015
|
-
|
1016
|
-
!Boolean methodsFor: 'converting'!
|
1017
|
-
|
1018
|
-
asJSON
|
1019
|
-
^self
|
1020
|
-
! !
|
1021
|
-
|
1022
|
-
!Boolean methodsFor: 'copying'!
|
1023
|
-
|
1024
|
-
shallowCopy
|
1025
|
-
^self
|
1026
|
-
!
|
1027
|
-
|
1028
|
-
deepCopy
|
1029
|
-
^self
|
1030
|
-
! !
|
1031
|
-
|
1032
|
-
!Boolean methodsFor: 'printing'!
|
1033
|
-
|
1034
|
-
printString
|
1035
|
-
<return self.toString()>
|
1036
|
-
! !
|
1037
|
-
|
1038
|
-
Object subclass: #Date
|
1039
|
-
instanceVariableNames: ''
|
1040
|
-
category: 'Kernel-Objects'!
|
1041
|
-
!Date commentStamp!
|
1042
|
-
The Date class is used to work with dates and times. Therefore `Date today` and `Date now` are both valid in
|
1043
|
-
Amber and answer the same date object.
|
1044
|
-
|
1045
|
-
Date wraps the `Date()` JavaScript constructor, and Smalltalk date objects are JavaScript date objects.!
|
1046
|
-
|
1047
|
-
!Date methodsFor: 'accessing'!
|
1048
|
-
|
1049
|
-
year
|
1050
|
-
<return self.getFullYear()>
|
1051
|
-
!
|
1052
|
-
|
1053
|
-
month
|
1054
|
-
<return self.getMonth() + 1>
|
1055
|
-
!
|
1056
|
-
|
1057
|
-
month: aNumber
|
1058
|
-
<self.setMonth(aNumber - 1)>
|
1059
|
-
!
|
1060
|
-
|
1061
|
-
day
|
1062
|
-
^self dayOfWeek
|
1063
|
-
!
|
1064
|
-
|
1065
|
-
dayOfWeek
|
1066
|
-
<return self.getDay() + 1>
|
1067
|
-
!
|
1068
|
-
|
1069
|
-
dayOfWeek: aNumber
|
1070
|
-
<return self.setDay(aNumber - 1)>
|
1071
|
-
!
|
1072
|
-
|
1073
|
-
day: aNumber
|
1074
|
-
self day: aNumber
|
1075
|
-
!
|
1076
|
-
|
1077
|
-
year: aNumber
|
1078
|
-
<self.setFullYear(aNumber)>
|
1079
|
-
!
|
1080
|
-
|
1081
|
-
dayOfMonth
|
1082
|
-
<return self.getDate()>
|
1083
|
-
!
|
1084
|
-
|
1085
|
-
dayOfMonth: aNumber
|
1086
|
-
<self.setDate(aNumber)>
|
1087
|
-
!
|
1088
|
-
|
1089
|
-
time
|
1090
|
-
<return self.getTime()>
|
1091
|
-
!
|
1092
|
-
|
1093
|
-
time: aNumber
|
1094
|
-
<self.setTime(aNumber)>
|
1095
|
-
!
|
1096
|
-
|
1097
|
-
hours: aNumber
|
1098
|
-
<self.setHours(aNumber)>
|
1099
|
-
!
|
1100
|
-
|
1101
|
-
minutes: aNumber
|
1102
|
-
<self.setMinutes(aNumber)>
|
1103
|
-
!
|
1104
|
-
|
1105
|
-
seconds: aNumber
|
1106
|
-
<self.setSeconds(aNumber)>
|
1107
|
-
!
|
1108
|
-
|
1109
|
-
milliseconds: aNumber
|
1110
|
-
<self.setMilliseconds(aNumber)>
|
1111
|
-
!
|
1112
|
-
|
1113
|
-
hours
|
1114
|
-
<return self.getHours()>
|
1115
|
-
!
|
1116
|
-
|
1117
|
-
minutes
|
1118
|
-
<return self.getMinutes()>
|
1119
|
-
!
|
1120
|
-
|
1121
|
-
seconds
|
1122
|
-
<return self.getSeconds()>
|
1123
|
-
!
|
1124
|
-
|
1125
|
-
milliseconds
|
1126
|
-
<return self.getMilliseconds()>
|
1127
|
-
! !
|
1128
|
-
|
1129
|
-
!Date methodsFor: 'arithmetic'!
|
1130
|
-
|
1131
|
-
- aDate
|
1132
|
-
<return self - aDate>
|
1133
|
-
!
|
1134
|
-
|
1135
|
-
+ aDate
|
1136
|
-
<return self + aDate>
|
1137
|
-
! !
|
1138
|
-
|
1139
|
-
!Date methodsFor: 'comparing'!
|
1140
|
-
|
1141
|
-
< aDate
|
1142
|
-
<return self < aDate>
|
1143
|
-
!
|
1144
|
-
|
1145
|
-
> aDate
|
1146
|
-
<return self >> aDate>
|
762
|
+
|
763
|
+
negated
|
764
|
+
^0 - self
|
1147
765
|
!
|
1148
766
|
|
1149
|
-
|
1150
|
-
<return self
|
767
|
+
sqrt
|
768
|
+
<return Math.sqrt(self)>
|
1151
769
|
!
|
1152
770
|
|
1153
|
-
|
1154
|
-
|
771
|
+
squared
|
772
|
+
^self * self
|
1155
773
|
! !
|
1156
774
|
|
1157
|
-
!
|
1158
|
-
|
1159
|
-
asString
|
1160
|
-
<return self.toString()>
|
1161
|
-
!
|
775
|
+
!Number methodsFor: 'comparing'!
|
1162
776
|
|
1163
|
-
|
1164
|
-
|
777
|
+
< aNumber
|
778
|
+
"Inlined in the Compiler"
|
779
|
+
<return self < aNumber>
|
1165
780
|
!
|
1166
781
|
|
1167
|
-
|
1168
|
-
|
782
|
+
<= aNumber
|
783
|
+
"Inlined in the Compiler"
|
784
|
+
<return self <= aNumber>
|
1169
785
|
!
|
1170
786
|
|
1171
|
-
|
1172
|
-
|
787
|
+
= aNumber
|
788
|
+
aNumber isNumber ifFalse: [^false].
|
789
|
+
<return Number(self) == aNumber>
|
1173
790
|
!
|
1174
791
|
|
1175
|
-
|
1176
|
-
|
792
|
+
> aNumber
|
793
|
+
"Inlined in the Compiler"
|
794
|
+
<return self >> aNumber>
|
1177
795
|
!
|
1178
796
|
|
1179
|
-
|
1180
|
-
|
797
|
+
>= aNumber
|
798
|
+
"Inlined in the Compiler"
|
799
|
+
<return self >>= aNumber>
|
1181
800
|
! !
|
1182
801
|
|
1183
|
-
!
|
1184
|
-
|
1185
|
-
printString
|
1186
|
-
^self asString
|
1187
|
-
! !
|
802
|
+
!Number methodsFor: 'converting'!
|
1188
803
|
|
1189
|
-
|
804
|
+
& aNumber
|
805
|
+
<return self & aNumber>
|
806
|
+
!
|
1190
807
|
|
1191
|
-
|
1192
|
-
|
808
|
+
@ aNumber
|
809
|
+
^Point x: self y: aNumber
|
1193
810
|
!
|
1194
811
|
|
1195
|
-
|
1196
|
-
|
1197
|
-
^self new: aString
|
812
|
+
asJSON
|
813
|
+
^self
|
1198
814
|
!
|
1199
815
|
|
1200
|
-
|
1201
|
-
^self
|
816
|
+
asJavascript
|
817
|
+
^'(', self printString, ')'
|
1202
818
|
!
|
1203
819
|
|
1204
|
-
|
1205
|
-
^self
|
820
|
+
asPoint
|
821
|
+
^Point x: self y: self
|
1206
822
|
!
|
1207
823
|
|
1208
|
-
|
1209
|
-
^self
|
824
|
+
asString
|
825
|
+
^self printString
|
1210
826
|
!
|
1211
827
|
|
1212
|
-
|
1213
|
-
|
828
|
+
atRandom
|
829
|
+
^(Random new next * self) truncated + 1
|
1214
830
|
!
|
1215
831
|
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
aBlock value.
|
1220
|
-
^Date now - t
|
1221
|
-
! !
|
832
|
+
rounded
|
833
|
+
<return Math.round(self);>
|
834
|
+
!
|
1222
835
|
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
836
|
+
to: aNumber
|
837
|
+
| array first last count |
|
838
|
+
first := self truncated.
|
839
|
+
last := aNumber truncated + 1.
|
840
|
+
count := 1.
|
841
|
+
array := Array new.
|
842
|
+
(last - first) timesRepeat: [
|
843
|
+
array at: count put: first.
|
844
|
+
count := count + 1.
|
845
|
+
first := first + 1].
|
846
|
+
^array
|
847
|
+
!
|
1228
848
|
|
1229
|
-
|
849
|
+
to: stop by: step
|
850
|
+
| array value pos |
|
851
|
+
value := self.
|
852
|
+
array := Array new.
|
853
|
+
pos := 1.
|
854
|
+
step = 0 ifTrue: [self error: 'step must be non-zero'].
|
855
|
+
step < 0
|
856
|
+
ifTrue: [[ value >= stop ] whileTrue: [
|
857
|
+
array at: pos put: value.
|
858
|
+
pos := pos + 1.
|
859
|
+
value := value + step]]
|
860
|
+
ifFalse: [[ value <= stop ] whileTrue: [
|
861
|
+
array at: pos put: value.
|
862
|
+
pos := pos + 1.
|
863
|
+
value := value + step]].
|
864
|
+
^array
|
865
|
+
!
|
1230
866
|
|
1231
|
-
|
867
|
+
truncated
|
868
|
+
|result|
|
1232
869
|
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
870
|
+
self >= 0
|
871
|
+
ifTrue: [<result = Math.floor(self);>]
|
872
|
+
ifFalse: [<result = (Math.floor(self * (-1)) * (-1));>].
|
1236
873
|
|
1237
|
-
|
1238
|
-
"Kept for compatibility."
|
1239
|
-
self deprecatedAPI.
|
1240
|
-
^self subclass: aString instanceVariableNames: aString2 package: aString3
|
874
|
+
^ result
|
1241
875
|
!
|
1242
876
|
|
1243
|
-
|
1244
|
-
|
1245
|
-
superclass: self subclass: aString instanceVariableNames: aString2 package: aString3
|
877
|
+
| aNumber
|
878
|
+
<return self | aNumber>
|
1246
879
|
! !
|
1247
880
|
|
1248
|
-
!
|
881
|
+
!Number methodsFor: 'copying'!
|
1249
882
|
|
1250
|
-
|
1251
|
-
^
|
883
|
+
copy
|
884
|
+
^self
|
885
|
+
!
|
886
|
+
|
887
|
+
deepCopy
|
888
|
+
^self copy
|
1252
889
|
! !
|
1253
890
|
|
1254
|
-
!
|
891
|
+
!Number methodsFor: 'enumerating'!
|
1255
892
|
|
1256
|
-
|
1257
|
-
|
893
|
+
timesRepeat: aBlock
|
894
|
+
| integer count |
|
895
|
+
integer := self truncated.
|
896
|
+
count := 1.
|
897
|
+
[count > self] whileFalse: [
|
898
|
+
aBlock value.
|
899
|
+
count := count + 1]
|
1258
900
|
!
|
1259
901
|
|
1260
|
-
|
1261
|
-
|
902
|
+
to: stop by: step do: aBlock
|
903
|
+
| value |
|
904
|
+
value := self.
|
905
|
+
step = 0 ifTrue: [self error: 'step must be non-zero'].
|
906
|
+
step < 0
|
907
|
+
ifTrue: [[ value >= stop ] whileTrue: [
|
908
|
+
aBlock value: value.
|
909
|
+
value := value + step]]
|
910
|
+
ifFalse: [[ value <= stop ] whileTrue: [
|
911
|
+
aBlock value: value.
|
912
|
+
value := value + step]]
|
913
|
+
!
|
914
|
+
|
915
|
+
to: stop do: aBlock
|
916
|
+
"Evaluate aBlock for each number from self to aNumber."
|
917
|
+
| nextValue |
|
918
|
+
nextValue := self.
|
919
|
+
[nextValue <= stop]
|
920
|
+
whileTrue:
|
921
|
+
[aBlock value: nextValue.
|
922
|
+
nextValue := nextValue + 1]
|
1262
923
|
! !
|
1263
924
|
|
1264
|
-
!
|
925
|
+
!Number methodsFor: 'printing'!
|
926
|
+
|
927
|
+
printShowingDecimalPlaces: placesDesired
|
928
|
+
<return self.toFixed(placesDesired)>
|
929
|
+
!
|
1265
930
|
|
1266
931
|
printString
|
1267
|
-
|
932
|
+
<return String(self)>
|
1268
933
|
! !
|
1269
934
|
|
1270
|
-
!
|
935
|
+
!Number methodsFor: 'testing'!
|
1271
936
|
|
1272
|
-
|
1273
|
-
|
1274
|
-
^self ifNil: aBlock ifNotNil: []
|
937
|
+
even
|
938
|
+
^ 0 = (self \\ 2)
|
1275
939
|
!
|
1276
940
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
^self
|
941
|
+
isNumber
|
942
|
+
^true
|
1280
943
|
!
|
1281
944
|
|
1282
|
-
|
1283
|
-
|
1284
|
-
^aBlock value
|
945
|
+
isZero
|
946
|
+
^self = 0
|
1285
947
|
!
|
1286
948
|
|
1287
|
-
|
1288
|
-
"
|
1289
|
-
^anotherBlock value
|
1290
|
-
!
|
949
|
+
negative
|
950
|
+
"Answer whether the receiver is mathematically negative."
|
1291
951
|
|
1292
|
-
|
1293
|
-
^true
|
952
|
+
^ self < 0
|
1294
953
|
!
|
1295
954
|
|
1296
|
-
|
1297
|
-
^
|
1298
|
-
!
|
955
|
+
odd
|
956
|
+
^ self even not
|
957
|
+
!
|
1299
958
|
|
1300
|
-
|
959
|
+
positive
|
960
|
+
"Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
|
1301
961
|
|
1302
|
-
|
1303
|
-
self error: 'You cannot create new instances of UndefinedObject. Use nil'
|
962
|
+
^ self >= 0
|
1304
963
|
! !
|
1305
964
|
|
1306
|
-
|
1307
|
-
instanceVariableNames: ''
|
1308
|
-
category: 'Kernel-Objects'!
|
1309
|
-
!Date commentStamp!
|
1310
|
-
The Date class is used to work with dates and times. Therefore `Date today` and `Date now` are both valid in
|
1311
|
-
Amber and answer the same date object.
|
965
|
+
!Number methodsFor: 'timeouts/intervals'!
|
1312
966
|
|
1313
|
-
|
967
|
+
clearInterval
|
968
|
+
<clearInterval(Number(self))>
|
969
|
+
!
|
1314
970
|
|
1315
|
-
|
971
|
+
clearTimeout
|
972
|
+
<clearTimeout(Number(self))>
|
973
|
+
! !
|
1316
974
|
|
1317
|
-
|
1318
|
-
<return self.getFullYear()>
|
1319
|
-
!
|
975
|
+
!Number class methodsFor: 'instance creation'!
|
1320
976
|
|
1321
|
-
|
1322
|
-
<return
|
1323
|
-
!
|
977
|
+
pi
|
978
|
+
<return Math.PI>
|
979
|
+
! !
|
1324
980
|
|
1325
|
-
|
1326
|
-
|
1327
|
-
!
|
981
|
+
Object subclass: #Package
|
982
|
+
instanceVariableNames: 'commitPathJs commitPathSt'
|
983
|
+
package: 'Kernel-Objects'!
|
984
|
+
!Package commentStamp!
|
985
|
+
A Package is similar to a "class category" typically found in other Smalltalks like Pharo or Squeak. Amber does not have class categories anymore, it had in the beginning but now each class in the system knows which package it belongs to.
|
1328
986
|
|
1329
|
-
|
1330
|
-
|
1331
|
-
!
|
987
|
+
A Package has a name, an Array of "requires", a comment and a Dictionary with other optional key value attributes. A Package can also be queried for its classes, but it will then resort to a reverse scan of all classes to find them.
|
988
|
+
Packages are manipulated through "Smalltalk current", like for example finding one based on a name:
|
1332
989
|
|
1333
|
-
|
1334
|
-
<return self.getDay() + 1>
|
1335
|
-
!
|
990
|
+
Smalltalk current packageAt: 'Kernel'
|
1336
991
|
|
1337
|
-
|
1338
|
-
<return self.setDay(aNumber - 1)>
|
1339
|
-
!
|
992
|
+
...but you can also use:
|
1340
993
|
|
1341
|
-
|
1342
|
-
self day: aNumber
|
1343
|
-
!
|
994
|
+
Package named: 'Kernel'
|
1344
995
|
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
996
|
+
A Package differs slightly from a Monticello package which can span multiple class categories using a naming convention based on hyphenation. But just as in Monticello a Package supports "class extensions" so a Package
|
997
|
+
can define behaviors in foreign classes using a naming convention for method categories where the category starts with an asterisk and then the name of the owning package follows. This can easily be seen in for example class
|
998
|
+
String where the method category "*IDE" defines #inspectOn: which thus is a method belonging to the IDE package.
|
1348
999
|
|
1349
|
-
|
1350
|
-
<return self.getDate()>
|
1351
|
-
!
|
1000
|
+
You can fetch a package from the server:
|
1352
1001
|
|
1353
|
-
|
1354
|
-
<self.setDate(aNumber)>
|
1355
|
-
!
|
1002
|
+
Package fetch: 'Additional-Examples'!
|
1356
1003
|
|
1357
|
-
|
1358
|
-
|
1004
|
+
!Package methodsFor: 'accessing'!
|
1005
|
+
|
1006
|
+
commitPathJs
|
1007
|
+
^ commitPathJs ifNil: [self class defaultCommitPathJs]
|
1359
1008
|
!
|
1360
1009
|
|
1361
|
-
|
1362
|
-
|
1010
|
+
commitPathJs: aString
|
1011
|
+
commitPathJs := aString
|
1363
1012
|
!
|
1364
1013
|
|
1365
|
-
|
1366
|
-
|
1014
|
+
commitPathSt
|
1015
|
+
^ commitPathSt ifNil: [self class defaultCommitPathSt]
|
1367
1016
|
!
|
1368
1017
|
|
1369
|
-
|
1370
|
-
|
1018
|
+
commitPathSt: aString
|
1019
|
+
commitPathSt := aString
|
1371
1020
|
!
|
1372
1021
|
|
1373
|
-
|
1374
|
-
|
1022
|
+
dependencies
|
1023
|
+
^self propertyAt: 'dependencies' ifAbsent: [#()]
|
1375
1024
|
!
|
1376
1025
|
|
1377
|
-
|
1378
|
-
|
1026
|
+
dependencies: anArray
|
1027
|
+
^self propertyAt: 'dependencies' put: anArray
|
1379
1028
|
!
|
1380
1029
|
|
1381
|
-
|
1382
|
-
<return self.
|
1030
|
+
name
|
1031
|
+
<return self.pkgName>
|
1383
1032
|
!
|
1384
1033
|
|
1385
|
-
|
1386
|
-
<
|
1034
|
+
name: aString
|
1035
|
+
<self.pkgName = aString>
|
1387
1036
|
!
|
1388
1037
|
|
1389
|
-
|
1390
|
-
|
1038
|
+
properties
|
1039
|
+
^Smalltalk current readJSObject: (self basicAt: 'properties')
|
1391
1040
|
!
|
1392
1041
|
|
1393
|
-
|
1394
|
-
|
1042
|
+
properties: aDict
|
1043
|
+
"We store it as a javascript object."
|
1044
|
+
|
1045
|
+
| object |
|
1046
|
+
<object = {};>.
|
1047
|
+
aDict keysAndValuesDo: [:key :value |
|
1048
|
+
<object[key] = value>.
|
1049
|
+
].
|
1050
|
+
<return self.properties = object>
|
1395
1051
|
! !
|
1396
1052
|
|
1397
|
-
!
|
1053
|
+
!Package methodsFor: 'classes'!
|
1398
1054
|
|
1399
|
-
|
1400
|
-
|
1055
|
+
classes
|
1056
|
+
"We need to do a reverse scan."
|
1057
|
+
^Smalltalk current classes select: [:c | c package == self]
|
1401
1058
|
!
|
1402
1059
|
|
1403
|
-
|
1404
|
-
|
1060
|
+
sortedClasses
|
1061
|
+
"Answer all classes in the receiver, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)."
|
1062
|
+
|
1063
|
+
^self class sortedClasses: self classes
|
1405
1064
|
! !
|
1406
1065
|
|
1407
|
-
!
|
1066
|
+
!Package methodsFor: 'printing'!
|
1408
1067
|
|
1409
|
-
|
1410
|
-
|
1411
|
-
!
|
1068
|
+
printString
|
1069
|
+
^self name
|
1070
|
+
! !
|
1412
1071
|
|
1413
|
-
|
1414
|
-
|
1072
|
+
!Package methodsFor: 'private'!
|
1073
|
+
|
1074
|
+
jsProperties
|
1075
|
+
<return self.properties>
|
1415
1076
|
!
|
1416
1077
|
|
1417
|
-
|
1418
|
-
<return self
|
1078
|
+
jsProperties: aJSObject
|
1079
|
+
<return self.properties = aJSObject>
|
1419
1080
|
!
|
1420
1081
|
|
1421
|
-
|
1422
|
-
<return self
|
1082
|
+
propertiesAsJSON
|
1083
|
+
<return JSON.stringify(self.properties)>
|
1423
1084
|
! !
|
1424
1085
|
|
1425
|
-
!
|
1426
|
-
|
1427
|
-
asString
|
1428
|
-
<return self.toString()>
|
1429
|
-
!
|
1086
|
+
!Package methodsFor: 'properties'!
|
1430
1087
|
|
1431
|
-
|
1432
|
-
^self time
|
1433
|
-
!
|
1088
|
+
propertyAt: key
|
1434
1089
|
|
1435
|
-
|
1436
|
-
<return self.toDateString()>
|
1090
|
+
<return self.properties[key]>
|
1437
1091
|
!
|
1438
1092
|
|
1439
|
-
|
1440
|
-
<return self.toTimeString()>
|
1441
|
-
!
|
1093
|
+
propertyAt: key ifAbsent: block
|
1442
1094
|
|
1443
|
-
|
1444
|
-
<return self.toLocaleString()>
|
1095
|
+
^(self propertyAt: key) ifNil: [block value]
|
1445
1096
|
!
|
1446
1097
|
|
1447
|
-
|
1448
|
-
^self asMilliseconds
|
1449
|
-
! !
|
1450
|
-
|
1451
|
-
!Date methodsFor: 'printing'!
|
1098
|
+
propertyAt: key put: value
|
1452
1099
|
|
1453
|
-
|
1454
|
-
^self asString
|
1100
|
+
<return self.properties[key] = value>
|
1455
1101
|
! !
|
1456
1102
|
|
1457
|
-
|
1458
|
-
|
1459
|
-
new: anObject
|
1460
|
-
<return new Date(anObject)>
|
1461
|
-
!
|
1103
|
+
Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
|
1462
1104
|
|
1463
|
-
|
1464
|
-
"Example: Date fromString('2011/04/15 00:00:00')"
|
1465
|
-
^self new: aString
|
1466
|
-
!
|
1105
|
+
!Package class methodsFor: 'commit paths'!
|
1467
1106
|
|
1468
|
-
|
1469
|
-
^
|
1107
|
+
defaultCommitPathJs
|
1108
|
+
^ defaultCommitPathJs ifNil: [ defaultCommitPathJs := 'js']
|
1470
1109
|
!
|
1471
1110
|
|
1472
|
-
|
1473
|
-
|
1111
|
+
defaultCommitPathJs: aString
|
1112
|
+
defaultCommitPathJs := aString
|
1474
1113
|
!
|
1475
1114
|
|
1476
|
-
|
1477
|
-
^
|
1115
|
+
defaultCommitPathSt
|
1116
|
+
^ defaultCommitPathSt ifNil: [ defaultCommitPathSt := 'st']
|
1478
1117
|
!
|
1479
1118
|
|
1480
|
-
|
1481
|
-
|
1119
|
+
defaultCommitPathSt: aString
|
1120
|
+
defaultCommitPathSt := aString
|
1482
1121
|
!
|
1483
1122
|
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
aBlock value.
|
1488
|
-
^Date now - t
|
1123
|
+
resetCommitPaths
|
1124
|
+
defaultCommitPathJs := nil.
|
1125
|
+
defaultCommitPathSt := nil.
|
1489
1126
|
! !
|
1490
1127
|
|
1491
|
-
|
1492
|
-
instanceVariableNames: 'jsObject'
|
1493
|
-
category: 'Kernel-Objects'!
|
1494
|
-
!JSObjectProxy commentStamp!
|
1495
|
-
JSObjectProxy handles sending messages to JavaScript object, therefore accessing JavaScript objects from Amber is transparent.
|
1496
|
-
JSOjbectProxy makes intensive use of `#doesNotUnderstand:`.
|
1497
|
-
|
1498
|
-
## Examples
|
1499
|
-
|
1500
|
-
JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
|
1501
|
-
|
1502
|
-
window alert: 'hello world'.
|
1503
|
-
window inspect.
|
1504
|
-
(window jQuery: 'body') append: 'hello world'
|
1505
|
-
|
1506
|
-
Smalltalk messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.
|
1507
|
-
|
1508
|
-
## Message conversion rules
|
1509
|
-
|
1510
|
-
- `someUser name` becomes `someUser.name`
|
1511
|
-
- `someUser name: 'John'` becomes `someUser name = "John"`
|
1512
|
-
- `console log: 'hello world'` becomes `console.log('hello world')`
|
1513
|
-
- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
|
1514
|
-
|
1515
|
-
__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
|
1516
|
-
|
1517
|
-
!JSObjectProxy methodsFor: 'accessing'!
|
1128
|
+
!Package class methodsFor: 'loading-storing'!
|
1518
1129
|
|
1519
|
-
|
1520
|
-
|
1130
|
+
commitToLocalStorage: aPackageName
|
1131
|
+
| key sourceCode |
|
1132
|
+
key := 'smalltalk.packages.' , aPackageName.
|
1133
|
+
sourceCode := Exporter new exportPackage: aPackageName.
|
1134
|
+
<localStorage[key] = escape(sourceCode)>
|
1521
1135
|
!
|
1522
1136
|
|
1523
|
-
|
1524
|
-
|
1137
|
+
fetch: aPackageName
|
1138
|
+
self fetch: aPackageName prefix: self defaultCommitPathJs, '/'
|
1525
1139
|
!
|
1526
1140
|
|
1527
|
-
|
1528
|
-
|
1529
|
-
attr := aSymbol asString.
|
1530
|
-
<return self['@jsObject'][attr]>
|
1141
|
+
fetch: aPackageName prefix: aPrefix
|
1142
|
+
jQuery getScript: (aPrefix , aPackageName , '.js') onSuccess: [ Package init: aPackageName ]
|
1531
1143
|
!
|
1532
1144
|
|
1533
|
-
|
1534
|
-
|
|
1535
|
-
|
1536
|
-
|
1145
|
+
init: aPackageName
|
1146
|
+
(smalltalk classes select: [ :each | <each.pkg.pkgName == aPackageName> ])
|
1147
|
+
do: [ :each | <smalltalk.init(each)> ];
|
1148
|
+
do: [ :each | each initialize ]
|
1537
1149
|
! !
|
1538
1150
|
|
1539
|
-
!
|
1151
|
+
!Package class methodsFor: 'not yet classified'!
|
1540
1152
|
|
1541
|
-
|
1542
|
-
^self jsObject toString
|
1543
|
-
!
|
1153
|
+
named: aPackageName
|
1544
1154
|
|
1545
|
-
|
1546
|
-
| variables |
|
1547
|
-
variables := Dictionary new.
|
1548
|
-
variables at: '#self' put: self jsObject.
|
1549
|
-
anInspector setLabel: self printString.
|
1550
|
-
<for(var i in self['@jsObject']) {
|
1551
|
-
variables._at_put_(i, self['@jsObject'][i]);
|
1552
|
-
}>.
|
1553
|
-
anInspector setVariables: variables
|
1155
|
+
^Smalltalk current packageAt: aPackageName
|
1554
1156
|
!
|
1555
1157
|
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
selector := aMessage selector.
|
1560
|
-
jsSelector := selector asJavaScriptSelector.
|
1561
|
-
arguments := aMessage arguments.
|
1562
|
-
<if(obj[jsSelector] !!= undefined) {return smalltalk.send(obj, jsSelector, arguments)}>.
|
1563
|
-
super doesNotUnderstand: aMessage
|
1158
|
+
named: aPackageName ifAbsent: aBlock
|
1159
|
+
|
1160
|
+
^Smalltalk current packageAt: aPackageName ifAbsent: aBlock
|
1564
1161
|
! !
|
1565
1162
|
|
1566
|
-
!
|
1163
|
+
!Package class methodsFor: 'sorting'!
|
1164
|
+
|
1165
|
+
sortedClasses: classes
|
1166
|
+
"Answer classes, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)"
|
1567
1167
|
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1168
|
+
| children others nodes expandedClasses |
|
1169
|
+
children := #().
|
1170
|
+
others := #().
|
1171
|
+
classes do: [:each |
|
1172
|
+
(classes includes: each superclass)
|
1173
|
+
ifFalse: [children add: each]
|
1174
|
+
ifTrue: [others add: each]].
|
1175
|
+
nodes := children collect: [:each |
|
1176
|
+
ClassSorterNode on: each classes: others level: 0].
|
1177
|
+
nodes := nodes sorted: [:a :b | a theClass name <= b theClass name ].
|
1178
|
+
expandedClasses := Array new.
|
1179
|
+
nodes do: [:aNode |
|
1180
|
+
aNode traverseClassesWith: expandedClasses].
|
1181
|
+
^expandedClasses
|
1572
1182
|
! !
|
1573
1183
|
|
1574
1184
|
Object subclass: #Point
|
1575
1185
|
instanceVariableNames: 'x y'
|
1576
|
-
|
1186
|
+
package: 'Kernel-Objects'!
|
1577
1187
|
!Point commentStamp!
|
1578
1188
|
A `Point` represents an x-y pair of numbers usually designating a geometric coordinate.
|
1579
1189
|
Points are traditionally created using the binary `#@` message to a number:
|
@@ -1600,16 +1210,16 @@ x
|
|
1600
1210
|
^x
|
1601
1211
|
!
|
1602
1212
|
|
1213
|
+
x: aNumber
|
1214
|
+
x := aNumber
|
1215
|
+
!
|
1216
|
+
|
1603
1217
|
y
|
1604
1218
|
^y
|
1605
1219
|
!
|
1606
1220
|
|
1607
1221
|
y: aNumber
|
1608
1222
|
y := aNumber
|
1609
|
-
!
|
1610
|
-
|
1611
|
-
x: aNumber
|
1612
|
-
x := aNumber
|
1613
1223
|
! !
|
1614
1224
|
|
1615
1225
|
!Point methodsFor: 'arithmetic'!
|
@@ -1673,7 +1283,7 @@ x: aNumber y: anotherNumber
|
|
1673
1283
|
|
1674
1284
|
Object subclass: #Random
|
1675
1285
|
instanceVariableNames: ''
|
1676
|
-
|
1286
|
+
package: 'Kernel-Objects'!
|
1677
1287
|
!Random commentStamp!
|
1678
1288
|
`Random` is a random number generator and is implemented as a trivial wrapper around javascript `Math.random()` and is used like this:
|
1679
1289
|
|
@@ -1711,3 +1321,248 @@ next: anInteger
|
|
1711
1321
|
^(1 to: anInteger) collect: [:each | self next]
|
1712
1322
|
! !
|
1713
1323
|
|
1324
|
+
Object subclass: #Smalltalk
|
1325
|
+
instanceVariableNames: ''
|
1326
|
+
package: 'Kernel-Objects'!
|
1327
|
+
!Smalltalk commentStamp!
|
1328
|
+
Smalltalk has only one instance, accessed with `Smalltalk current`.
|
1329
|
+
It represents the global JavaScript variable `smalltalk` declared in `js/boot.js`.
|
1330
|
+
|
1331
|
+
The `smalltalk` object holds all class and packages defined in the system.
|
1332
|
+
|
1333
|
+
## Classes
|
1334
|
+
|
1335
|
+
Classes can be accessed using the following methods:
|
1336
|
+
|
1337
|
+
- `#classes` answers the full list of Smalltalk classes in the system
|
1338
|
+
- `#at:` answers a specific class of `nil`
|
1339
|
+
|
1340
|
+
## Packages
|
1341
|
+
|
1342
|
+
Packages can be accessed using the following methods:
|
1343
|
+
|
1344
|
+
- `#packages` answers the full list of packages
|
1345
|
+
- `#packageAt:` answers a specific class of `nil`
|
1346
|
+
|
1347
|
+
__note:__ classes and packages are accessed using strings, not symbols
|
1348
|
+
|
1349
|
+
## Parsing
|
1350
|
+
|
1351
|
+
The `#parse:` method is used to parse Smalltalk source code.
|
1352
|
+
It requires the `Compiler` package and the `js/parser.js` parser file in order to work!
|
1353
|
+
|
1354
|
+
!Smalltalk methodsFor: 'accessing'!
|
1355
|
+
|
1356
|
+
at: aString
|
1357
|
+
<return self[aString]>
|
1358
|
+
!
|
1359
|
+
|
1360
|
+
basicParse: aString
|
1361
|
+
<return smalltalk.parser.parse(aString)>
|
1362
|
+
!
|
1363
|
+
|
1364
|
+
classes
|
1365
|
+
<return self.classes()>
|
1366
|
+
!
|
1367
|
+
|
1368
|
+
parse: aString
|
1369
|
+
| result |
|
1370
|
+
self try: [result := self basicParse: aString] catch: [:ex | (self parseError: ex parsing: aString) signal].
|
1371
|
+
^result
|
1372
|
+
!
|
1373
|
+
|
1374
|
+
parseError: anException parsing: aString
|
1375
|
+
| row col message lines badLine code |
|
1376
|
+
<row = anException.line;
|
1377
|
+
col = anException.column;
|
1378
|
+
message = anException.message;>.
|
1379
|
+
lines := aString lines.
|
1380
|
+
badLine := lines at: row.
|
1381
|
+
badLine := (badLine copyFrom: 1 to: col - 1), ' ===>', (badLine copyFrom: col to: badLine size).
|
1382
|
+
lines at: row put: badLine.
|
1383
|
+
code := String streamContents: [:s |
|
1384
|
+
lines withIndexDo: [:l :i |
|
1385
|
+
s nextPutAll: i asString, ': ', l, String lf]].
|
1386
|
+
^ Error new messageText: ('Parse error on line ' , row , ' column ' , col , ' : ' , message , ' Below is code with line numbers and ===> marker inserted:' , String lf, code)
|
1387
|
+
!
|
1388
|
+
|
1389
|
+
readJSObject: anObject
|
1390
|
+
<return self.readJSObject(anObject)>
|
1391
|
+
!
|
1392
|
+
|
1393
|
+
reservedWords
|
1394
|
+
"JavaScript reserved words"
|
1395
|
+
<return self.reservedWords>
|
1396
|
+
!
|
1397
|
+
|
1398
|
+
send: aSelector to: anObject arguments: aCollection
|
1399
|
+
| selector |
|
1400
|
+
selector := aSelector asString asSelector.
|
1401
|
+
<self.send(anObject, selector, aCollection)>
|
1402
|
+
! !
|
1403
|
+
|
1404
|
+
!Smalltalk methodsFor: 'classes'!
|
1405
|
+
|
1406
|
+
removeClass: aClass
|
1407
|
+
aClass isMetaclass ifTrue: [self error: aClass asString, ' is a Metaclass and cannot be removed!!'].
|
1408
|
+
aClass methodDictionary values do: [:each |
|
1409
|
+
aClass removeCompiledMethod: each].
|
1410
|
+
aClass class methodDictionary values do: [:each |
|
1411
|
+
aClass class removeCompiledMethod: each].
|
1412
|
+
self basicDelete: aClass name
|
1413
|
+
! !
|
1414
|
+
|
1415
|
+
!Smalltalk methodsFor: 'packages'!
|
1416
|
+
|
1417
|
+
packageAt: packageName
|
1418
|
+
<return self.packages[packageName]>
|
1419
|
+
!
|
1420
|
+
|
1421
|
+
packageAt: packageName ifAbsent: aBlock
|
1422
|
+
^(self packageAt: packageName) ifNil: aBlock
|
1423
|
+
!
|
1424
|
+
|
1425
|
+
packages
|
1426
|
+
"Return all Package instances in the system."
|
1427
|
+
|
1428
|
+
<return self.packages.all()>
|
1429
|
+
!
|
1430
|
+
|
1431
|
+
removePackage: packageName
|
1432
|
+
"Removes a package and all its classes."
|
1433
|
+
|
1434
|
+
| pkg |
|
1435
|
+
pkg := self packageAt: packageName ifAbsent: [self error: 'Missing package: ', packageName].
|
1436
|
+
pkg classes do: [:each |
|
1437
|
+
self removeClass: each].
|
1438
|
+
self deletePackage: packageName
|
1439
|
+
!
|
1440
|
+
|
1441
|
+
renamePackage: packageName to: newName
|
1442
|
+
"Rename a package."
|
1443
|
+
|
1444
|
+
| pkg |
|
1445
|
+
pkg := self packageAt: packageName ifAbsent: [self error: 'Missing package: ', packageName].
|
1446
|
+
(self packageAt: newName) ifNotNil: [self error: 'Already exists a package called: ', newName].
|
1447
|
+
<smalltalk.packages[newName] = smalltalk.packages[packageName]>.
|
1448
|
+
pkg name: newName.
|
1449
|
+
self deletePackage: packageName.
|
1450
|
+
! !
|
1451
|
+
|
1452
|
+
!Smalltalk methodsFor: 'private'!
|
1453
|
+
|
1454
|
+
createPackage: packageName
|
1455
|
+
"Create and bind a new package with given name and return it."
|
1456
|
+
|
1457
|
+
<return smalltalk.addPackage(packageName, nil)>
|
1458
|
+
!
|
1459
|
+
|
1460
|
+
createPackage: packageName properties: aDict
|
1461
|
+
"Create and bind a new package with given name and return it."
|
1462
|
+
|
1463
|
+
| object |
|
1464
|
+
<object = {};>.
|
1465
|
+
aDict keysAndValuesDo: [:key :value |
|
1466
|
+
<object[key] = value>.
|
1467
|
+
].
|
1468
|
+
<return smalltalk.addPackage(packageName, object)>
|
1469
|
+
!
|
1470
|
+
|
1471
|
+
deletePackage: packageName
|
1472
|
+
"Deletes a package by deleting its binding, but does not check if it contains classes etc.
|
1473
|
+
To remove a package, use #removePackage instead."
|
1474
|
+
|
1475
|
+
<delete smalltalk.packages[packageName]>
|
1476
|
+
! !
|
1477
|
+
|
1478
|
+
Smalltalk class instanceVariableNames: 'current'!
|
1479
|
+
|
1480
|
+
!Smalltalk class methodsFor: 'accessing'!
|
1481
|
+
|
1482
|
+
current
|
1483
|
+
<return smalltalk>
|
1484
|
+
! !
|
1485
|
+
|
1486
|
+
Object subclass: #UndefinedObject
|
1487
|
+
instanceVariableNames: ''
|
1488
|
+
package: 'Kernel-Objects'!
|
1489
|
+
!UndefinedObject commentStamp!
|
1490
|
+
UndefinedObject describes the behavior of its sole instance, `nil`. `nil` represents a prior value for variables that have not been initialized, or for results which are meaningless.
|
1491
|
+
|
1492
|
+
`nil` is the Smalltalk representation of the `undefined` JavaScript object.!
|
1493
|
+
|
1494
|
+
!UndefinedObject methodsFor: 'class creation'!
|
1495
|
+
|
1496
|
+
subclass: aString instanceVariableNames: anotherString
|
1497
|
+
^self subclass: aString instanceVariableNames: anotherString package: nil
|
1498
|
+
!
|
1499
|
+
|
1500
|
+
subclass: aString instanceVariableNames: aString2 category: aString3
|
1501
|
+
"Kept for compatibility."
|
1502
|
+
self deprecatedAPI.
|
1503
|
+
^self subclass: aString instanceVariableNames: aString2 package: aString3
|
1504
|
+
!
|
1505
|
+
|
1506
|
+
subclass: aString instanceVariableNames: aString2 package: aString3
|
1507
|
+
^ClassBuilder new
|
1508
|
+
superclass: self subclass: aString instanceVariableNames: aString2 package: aString3
|
1509
|
+
! !
|
1510
|
+
|
1511
|
+
!UndefinedObject methodsFor: 'converting'!
|
1512
|
+
|
1513
|
+
asJSON
|
1514
|
+
^null
|
1515
|
+
! !
|
1516
|
+
|
1517
|
+
!UndefinedObject methodsFor: 'copying'!
|
1518
|
+
|
1519
|
+
deepCopy
|
1520
|
+
^self
|
1521
|
+
!
|
1522
|
+
|
1523
|
+
shallowCopy
|
1524
|
+
^self
|
1525
|
+
! !
|
1526
|
+
|
1527
|
+
!UndefinedObject methodsFor: 'printing'!
|
1528
|
+
|
1529
|
+
printString
|
1530
|
+
^'nil'
|
1531
|
+
! !
|
1532
|
+
|
1533
|
+
!UndefinedObject methodsFor: 'testing'!
|
1534
|
+
|
1535
|
+
ifNil: aBlock
|
1536
|
+
"inlined in the Compiler"
|
1537
|
+
^self ifNil: aBlock ifNotNil: []
|
1538
|
+
!
|
1539
|
+
|
1540
|
+
ifNil: aBlock ifNotNil: anotherBlock
|
1541
|
+
"inlined in the Compiler"
|
1542
|
+
^aBlock value
|
1543
|
+
!
|
1544
|
+
|
1545
|
+
ifNotNil: aBlock
|
1546
|
+
"inlined in the Compiler"
|
1547
|
+
^self
|
1548
|
+
!
|
1549
|
+
|
1550
|
+
ifNotNil: aBlock ifNil: anotherBlock
|
1551
|
+
"inlined in the Compiler"
|
1552
|
+
^anotherBlock value
|
1553
|
+
!
|
1554
|
+
|
1555
|
+
isNil
|
1556
|
+
^true
|
1557
|
+
!
|
1558
|
+
|
1559
|
+
notNil
|
1560
|
+
^false
|
1561
|
+
! !
|
1562
|
+
|
1563
|
+
!UndefinedObject class methodsFor: 'instance creation'!
|
1564
|
+
|
1565
|
+
new
|
1566
|
+
self error: 'You cannot create new instances of UndefinedObject. Use nil'
|
1567
|
+
! !
|
1568
|
+
|