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-Objects' properties: #{}!
2
2
  nil subclass: #Object
3
3
  instanceVariableNames: ''
4
- category: 'Kernel-Objects'!
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
- yourself
45
- ^self
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
- size
53
- self error: 'Object not indexable'
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
- basicAt: aString
69
- <return self[aString]>
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
- identityHash
81
- <return self.identityHash || (self.identityHash = smalltalk.nextId());>
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
- shallowCopy
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
- deepCopy
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]._deepCopy();
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
- error: aString
164
- Error signal: aString
165
- !
166
-
167
- subclassResponsibility
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
- deprecatedAPI
192
- "Just a simple way to deprecate methods.
193
- #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
194
- but it could in the future."
195
- console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'
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
- printString
224
- ^'a ', self class name
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
- log: aString block: aBlock
242
+ printString
243
+ ^'a ', self class name
244
+ !
232
245
 
233
- | result |
234
- console log: aString, ' time: ', (Date millisecondsToRun: [result := aBlock value]) printString.
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
- isNil
279
+ isClass
282
280
  ^false
283
281
  !
284
282
 
285
- notNil
286
- ^self isNil not
283
+ isKindOf: aClass
284
+ ^(self isMemberOf: aClass)
285
+ ifTrue: [true]
286
+ ifFalse: [self class inheritsFrom: aClass]
287
287
  !
288
288
 
289
- isClass
290
- ^false
289
+ isMemberOf: aClass
290
+ ^self class = aClass
291
291
  !
292
292
 
293
293
  isMetaclass
294
294
  ^false
295
295
  !
296
296
 
297
- isNumber
297
+ isNil
298
298
  ^false
299
299
  !
300
300
 
301
- isString
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: #Smalltalk
331
+ Object subclass: #Boolean
320
332
  instanceVariableNames: ''
321
- category: 'Kernel-Objects'!
322
- !Smalltalk commentStamp!
323
- Smalltalk has only one instance, accessed with `Smalltalk current`.
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
- Packages can be accessed using the following methods:
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
- - `#packages` answers the full list of packages
340
- - `#packageAt:` answers a specific class of `nil`
340
+ !Boolean methodsFor: 'comparing'!
341
341
 
342
- __note:__ classes and packages are accessed using strings, not symbols
342
+ = aBoolean
343
+ aBoolean class = self class ifFalse: [^false].
344
+ <return Boolean(self == true) == aBoolean>
345
+ !
343
346
 
344
- ## Parsing
347
+ == aBoolean
348
+ ^self = aBoolean
349
+ ! !
345
350
 
346
- The `#parse:` method is used to parse Smalltalk source code.
347
- It requires the `Compiler` package and the `js/parser.js` parser file in order to work!
351
+ !Boolean methodsFor: 'controlling'!
348
352
 
349
- !Smalltalk methodsFor: 'accessing'!
353
+ & aBoolean
354
+ <
355
+ if(self == true) {
356
+ return aBoolean;
357
+ } else {
358
+ return false;
359
+ }
360
+ >
361
+ !
350
362
 
351
- classes
352
- <return self.classes()>
363
+ and: aBlock
364
+ ^self = true
365
+ ifTrue: aBlock
366
+ ifFalse: [false]
353
367
  !
354
368
 
355
- at: aString
356
- <return self[aString]>
369
+ ifFalse: aBlock
370
+ "inlined in the Compiler"
371
+ ^self ifTrue: [] ifFalse: aBlock
357
372
  !
358
373
 
359
- basicParse: aString
360
- <return smalltalk.parser.parse(aString)>
374
+ ifFalse: aBlock ifTrue: anotherBlock
375
+ "inlined in the Compiler"
376
+ ^self ifTrue: anotherBlock ifFalse: aBlock
361
377
  !
362
378
 
363
- parse: aString
364
- | result |
365
- self try: [result := self basicParse: aString] catch: [:ex | (self parseError: ex parsing: aString) signal].
366
- ^result
379
+ ifTrue: aBlock
380
+ "inlined in the Compiler"
381
+ ^self ifTrue: aBlock ifFalse: []
367
382
  !
368
383
 
369
- parseError: anException parsing: aString
370
- | row col message lines badLine code |
371
- <row = anException.line;
372
- col = anException.column;
373
- message = anException.message;>.
374
- lines := aString lines.
375
- badLine := lines at: row.
376
- badLine := (badLine copyFrom: 1 to: col - 1), ' ===>', (badLine copyFrom: col to: badLine size).
377
- lines at: row put: badLine.
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
- reservedWords
385
- "JavaScript reserved words"
386
- <return self.reservedWords>
395
+ not
396
+ ^self = false
387
397
  !
388
398
 
389
- readJSObject: anObject
390
- <return self.readJSObject(anObject)>
399
+ or: aBlock
400
+ ^self = true
401
+ ifTrue: [true]
402
+ ifFalse: aBlock
391
403
  !
392
404
 
393
- send: aSelector to: anObject arguments: aCollection
394
- | selector |
395
- selector := aSelector asString asSelector.
396
- <self.send(anObject, selector, aCollection)>
405
+ | aBoolean
406
+ <
407
+ if(self == true) {
408
+ return true;
409
+ } else {
410
+ return aBoolean;
411
+ }
412
+ >
397
413
  ! !
398
414
 
399
- !Smalltalk methodsFor: 'classes'!
415
+ !Boolean methodsFor: 'converting'!
400
416
 
401
- removeClass: aClass
402
- aClass isMetaclass ifTrue: [self error: aClass asString, ' is a Metaclass and cannot be removed!!'].
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
- !Smalltalk methodsFor: 'packages'!
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
- packageAt: packageName ifAbsent: aBlock
423
- ^(self packageAt: packageName) ifNil: aBlock
423
+ deepCopy
424
+ ^self
424
425
  !
425
426
 
426
- removePackage: packageName
427
- "Removes a package and all its classes."
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
- renamePackage: packageName to: newName
437
- "Rename a package."
431
+ !Boolean methodsFor: 'printing'!
438
432
 
439
- | pkg |
440
- pkg := self packageAt: packageName ifAbsent: [self error: 'Missing package: ', packageName].
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
- !Smalltalk methodsFor: 'private'!
448
-
449
- createPackage: packageName
450
- "Create and bind a new package with given name and return it."
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
- <return smalltalk.addPackage(packageName, nil)>
453
- !
444
+ Date wraps the `Date()` JavaScript constructor, and Smalltalk date objects are JavaScript date objects.!
454
445
 
455
- deletePackage: packageName
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
- <delete smalltalk.packages[packageName]>
448
+ day
449
+ ^self dayOfWeek
460
450
  !
461
451
 
462
- createPackage: packageName properties: aDict
463
- "Create and bind a new package with given name and return it."
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
- 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.
488
- Packages are manipulated through "Smalltalk current", like for example finding one based on a name:
456
+ dayOfMonth
457
+ <return self.getDate()>
458
+ !
489
459
 
490
- Smalltalk current packageAt: 'Kernel'
460
+ dayOfMonth: aNumber
461
+ <self.setDate(aNumber)>
462
+ !
491
463
 
492
- ...but you can also use:
464
+ dayOfWeek
465
+ <return self.getDay() + 1>
466
+ !
493
467
 
494
- Package named: 'Kernel'
468
+ dayOfWeek: aNumber
469
+ <return self.setDay(aNumber - 1)>
470
+ !
495
471
 
496
- 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
497
- 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
498
- String where the method category "*IDE" defines #inspectOn: which thus is a method belonging to the IDE package.
472
+ hours
473
+ <return self.getHours()>
474
+ !
499
475
 
500
- You can fetch a package from the server:
476
+ hours: aNumber
477
+ <self.setHours(aNumber)>
478
+ !
501
479
 
502
- Package fetch: 'Additional-Examples'!
480
+ milliseconds
481
+ <return self.getMilliseconds()>
482
+ !
503
483
 
504
- !Package methodsFor: 'accessing'!
484
+ milliseconds: aNumber
485
+ <self.setMilliseconds(aNumber)>
486
+ !
505
487
 
506
- name
507
- <return self.pkgName>
488
+ minutes
489
+ <return self.getMinutes()>
508
490
  !
509
491
 
510
- name: aString
511
- <self.pkgName = aString>
492
+ minutes: aNumber
493
+ <self.setMinutes(aNumber)>
512
494
  !
513
495
 
514
- dependencies
515
- ^self propertyAt: 'dependencies' ifAbsent: [#()]
496
+ month
497
+ <return self.getMonth() + 1>
516
498
  !
517
499
 
518
- dependencies: anArray
519
- ^self propertyAt: 'dependencies' put: anArray
500
+ month: aNumber
501
+ <self.setMonth(aNumber - 1)>
520
502
  !
521
503
 
522
- properties
523
- ^Smalltalk current readJSObject: (self basicAt: 'properties')
504
+ seconds
505
+ <return self.getSeconds()>
524
506
  !
525
507
 
526
- properties: aDict
527
- "We store it as a javascript object."
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
- commitPathJs
538
- ^ commitPathJs ifNil: [self class defaultCommitPathJs]
512
+ time
513
+ <return self.getTime()>
539
514
  !
540
515
 
541
- commitPathJs: aString
542
- commitPathJs := aString
516
+ time: aNumber
517
+ <self.setTime(aNumber)>
543
518
  !
544
519
 
545
- commitPathSt
546
- ^ commitPathSt ifNil: [self class defaultCommitPathSt]
520
+ year
521
+ <return self.getFullYear()>
547
522
  !
548
523
 
549
- commitPathSt: aString
550
- commitPathSt := aString
524
+ year: aNumber
525
+ <self.setFullYear(aNumber)>
551
526
  ! !
552
527
 
553
- !Package methodsFor: 'classes'!
528
+ !Date methodsFor: 'arithmetic'!
554
529
 
555
- classes
556
- "We need to do a reverse scan."
557
- ^Smalltalk current classes select: [:c | c package == self]
530
+ + aDate
531
+ <return self + aDate>
558
532
  !
559
533
 
560
- sortedClasses
561
- "Answer all classes in the receiver, sorted by superclass/subclasses"
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
- !Package methodsFor: 'printing'!
572
-
573
- printString
574
- ^self name
575
- ! !
538
+ !Date methodsFor: 'comparing'!
576
539
 
577
- !Package methodsFor: 'private'!
540
+ < aDate
541
+ <return self < aDate>
542
+ !
578
543
 
579
- propertiesAsJSON
580
- <return JSON.stringify(self.properties)>
544
+ <= aDate
545
+ <return self <= aDate>
581
546
  !
582
547
 
583
- jsProperties
584
- <return self.properties>
548
+ > aDate
549
+ <return self >> aDate>
585
550
  !
586
551
 
587
- jsProperties: aJSObject
588
- <return self.properties = aJSObject>
552
+ >= aDate
553
+ <return self >>= aDate>
589
554
  ! !
590
555
 
591
- !Package methodsFor: 'properties'!
556
+ !Date methodsFor: 'converting'!
592
557
 
593
- propertyAt: key
558
+ asDateString
559
+ <return self.toDateString()>
560
+ !
594
561
 
595
- <return self.properties[key]>
562
+ asLocaleString
563
+ <return self.toLocaleString()>
596
564
  !
597
565
 
598
- propertyAt: key put: value
566
+ asMilliseconds
567
+ ^self time
568
+ !
599
569
 
600
- <return self.properties[key] = value>
570
+ asNumber
571
+ ^self asMilliseconds
601
572
  !
602
573
 
603
- propertyAt: key ifAbsent: block
574
+ asString
575
+ <return self.toString()>
576
+ !
604
577
 
605
- ^(self propertyAt: key) ifNil: [block value]
578
+ asTimeString
579
+ <return self.toTimeString()>
606
580
  ! !
607
581
 
608
- Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
582
+ !Date methodsFor: 'printing'!
609
583
 
610
- !Package class methodsFor: 'commit paths'!
584
+ printString
585
+ ^self asString
586
+ ! !
611
587
 
612
- defaultCommitPathJs
613
- ^ defaultCommitPathJs ifNil: [ defaultCommitPathJs := 'js']
588
+ !Date class methodsFor: 'instance creation'!
589
+
590
+ fromMilliseconds: aNumber
591
+ ^self new: aNumber
614
592
  !
615
593
 
616
- defaultCommitPathJs: aString
617
- defaultCommitPathJs := aString
594
+ fromSeconds: aNumber
595
+ ^self fromMilliseconds: aNumber * 1000
618
596
  !
619
597
 
620
- defaultCommitPathSt
621
- ^ defaultCommitPathSt ifNil: [ defaultCommitPathSt := 'st']
598
+ fromString: aString
599
+ "Example: Date fromString('2011/04/15 00:00:00')"
600
+ ^self new: aString
622
601
  !
623
602
 
624
- defaultCommitPathSt: aString
625
- defaultCommitPathSt := aString
603
+ millisecondsToRun: aBlock
604
+ | t |
605
+ t := Date now.
606
+ aBlock value.
607
+ ^Date now - t
626
608
  !
627
609
 
628
- resetCommitPaths
629
- defaultCommitPathJs := nil.
630
- defaultCommitPathSt := nil.
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
- !Package class methodsFor: 'loading-storing'!
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
- fetch: aPackageName prefix: aPrefix
636
- jQuery getScript: (aPrefix , aPackageName , '.js') onSuccess: [ Package init: aPackageName ]
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
- fetch: aPackageName
640
- self fetch: aPackageName prefix: self defaultCommitPathJs, '/'
656
+ at: aSymbol put: anObject
657
+ | attr |
658
+ attr := aSymbol asString.
659
+ <self['@jsObject'][attr] = anObject>
641
660
  !
642
661
 
643
- commitToLocalStorage: aPackageName
644
- | key sourceCode |
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
- init: aPackageName
651
- (smalltalk classes select: [ :each | <each.pkg.pkgName == aPackageName> ])
652
- do: [ :each | <smalltalk.init(each)> ];
653
- do: [ :each | each initialize ]
666
+ jsObject: aJSObject
667
+ jsObject := aJSObject
654
668
  ! !
655
669
 
656
- !Package class methodsFor: 'not yet classified'!
670
+ !JSObjectProxy methodsFor: 'proxy'!
657
671
 
658
- named: aPackageName
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
- ^Smalltalk current packageAt: aPackageName
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
- named: aPackageName ifAbsent: aBlock
693
+ printString
694
+ ^self jsObject toString
695
+ ! !
664
696
 
665
- ^Smalltalk current packageAt: aPackageName ifAbsent: aBlock
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
- category: 'Kernel-Objects'!
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
- sqrt
731
- <return Math.sqrt(self)>
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
- asPoint
811
- ^Point x: self y: self
759
+ min: aNumber
760
+ <return Math.min(self, aNumber);>
812
761
  !
813
-
814
- to: stop by: step
815
- | array value pos |
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
- <= aDate
1150
- <return self <= aDate>
767
+ sqrt
768
+ <return Math.sqrt(self)>
1151
769
  !
1152
770
 
1153
- >= aDate
1154
- <return self >>= aDate>
771
+ squared
772
+ ^self * self
1155
773
  ! !
1156
774
 
1157
- !Date methodsFor: 'converting'!
1158
-
1159
- asString
1160
- <return self.toString()>
1161
- !
775
+ !Number methodsFor: 'comparing'!
1162
776
 
1163
- asMilliseconds
1164
- ^self time
777
+ < aNumber
778
+ "Inlined in the Compiler"
779
+ <return self < aNumber>
1165
780
  !
1166
781
 
1167
- asDateString
1168
- <return self.toDateString()>
782
+ <= aNumber
783
+ "Inlined in the Compiler"
784
+ <return self <= aNumber>
1169
785
  !
1170
786
 
1171
- asTimeString
1172
- <return self.toTimeString()>
787
+ = aNumber
788
+ aNumber isNumber ifFalse: [^false].
789
+ <return Number(self) == aNumber>
1173
790
  !
1174
791
 
1175
- asLocaleString
1176
- <return self.toLocaleString()>
792
+ > aNumber
793
+ "Inlined in the Compiler"
794
+ <return self >> aNumber>
1177
795
  !
1178
796
 
1179
- asNumber
1180
- ^self asMilliseconds
797
+ >= aNumber
798
+ "Inlined in the Compiler"
799
+ <return self >>= aNumber>
1181
800
  ! !
1182
801
 
1183
- !Date methodsFor: 'printing'!
1184
-
1185
- printString
1186
- ^self asString
1187
- ! !
802
+ !Number methodsFor: 'converting'!
1188
803
 
1189
- !Date class methodsFor: 'instance creation'!
804
+ & aNumber
805
+ <return self & aNumber>
806
+ !
1190
807
 
1191
- new: anObject
1192
- <return new Date(anObject)>
808
+ @ aNumber
809
+ ^Point x: self y: aNumber
1193
810
  !
1194
811
 
1195
- fromString: aString
1196
- "Example: Date fromString('2011/04/15 00:00:00')"
1197
- ^self new: aString
812
+ asJSON
813
+ ^self
1198
814
  !
1199
815
 
1200
- fromSeconds: aNumber
1201
- ^self fromMilliseconds: aNumber * 1000
816
+ asJavascript
817
+ ^'(', self printString, ')'
1202
818
  !
1203
819
 
1204
- fromMilliseconds: aNumber
1205
- ^self new: aNumber
820
+ asPoint
821
+ ^Point x: self y: self
1206
822
  !
1207
823
 
1208
- today
1209
- ^self new
824
+ asString
825
+ ^self printString
1210
826
  !
1211
827
 
1212
- now
1213
- ^self today
828
+ atRandom
829
+ ^(Random new next * self) truncated + 1
1214
830
  !
1215
831
 
1216
- millisecondsToRun: aBlock
1217
- | t |
1218
- t := Date now.
1219
- aBlock value.
1220
- ^Date now - t
1221
- ! !
832
+ rounded
833
+ <return Math.round(self);>
834
+ !
1222
835
 
1223
- Object subclass: #UndefinedObject
1224
- instanceVariableNames: ''
1225
- category: 'Kernel-Objects'!
1226
- !UndefinedObject commentStamp!
1227
- 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.
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
- `nil` is the Smalltalk representation of the `undefined` JavaScript object.!
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
- !UndefinedObject methodsFor: 'class creation'!
867
+ truncated
868
+ |result|
1232
869
 
1233
- subclass: aString instanceVariableNames: anotherString
1234
- ^self subclass: aString instanceVariableNames: anotherString package: nil
1235
- !
870
+ self >= 0
871
+ ifTrue: [<result = Math.floor(self);>]
872
+ ifFalse: [<result = (Math.floor(self * (-1)) * (-1));>].
1236
873
 
1237
- subclass: aString instanceVariableNames: aString2 category: aString3
1238
- "Kept for compatibility."
1239
- self deprecatedAPI.
1240
- ^self subclass: aString instanceVariableNames: aString2 package: aString3
874
+ ^ result
1241
875
  !
1242
876
 
1243
- subclass: aString instanceVariableNames: aString2 package: aString3
1244
- ^ClassBuilder new
1245
- superclass: self subclass: aString instanceVariableNames: aString2 package: aString3
877
+ | aNumber
878
+ <return self | aNumber>
1246
879
  ! !
1247
880
 
1248
- !UndefinedObject methodsFor: 'converting'!
881
+ !Number methodsFor: 'copying'!
1249
882
 
1250
- asJSON
1251
- ^null
883
+ copy
884
+ ^self
885
+ !
886
+
887
+ deepCopy
888
+ ^self copy
1252
889
  ! !
1253
890
 
1254
- !UndefinedObject methodsFor: 'copying'!
891
+ !Number methodsFor: 'enumerating'!
1255
892
 
1256
- shallowCopy
1257
- ^self
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
- deepCopy
1261
- ^self
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
- !UndefinedObject methodsFor: 'printing'!
925
+ !Number methodsFor: 'printing'!
926
+
927
+ printShowingDecimalPlaces: placesDesired
928
+ <return self.toFixed(placesDesired)>
929
+ !
1265
930
 
1266
931
  printString
1267
- ^'nil'
932
+ <return String(self)>
1268
933
  ! !
1269
934
 
1270
- !UndefinedObject methodsFor: 'testing'!
935
+ !Number methodsFor: 'testing'!
1271
936
 
1272
- ifNil: aBlock
1273
- "inlined in the Compiler"
1274
- ^self ifNil: aBlock ifNotNil: []
937
+ even
938
+ ^ 0 = (self \\ 2)
1275
939
  !
1276
940
 
1277
- ifNotNil: aBlock
1278
- "inlined in the Compiler"
1279
- ^self
941
+ isNumber
942
+ ^true
1280
943
  !
1281
944
 
1282
- ifNil: aBlock ifNotNil: anotherBlock
1283
- "inlined in the Compiler"
1284
- ^aBlock value
945
+ isZero
946
+ ^self = 0
1285
947
  !
1286
948
 
1287
- ifNotNil: aBlock ifNil: anotherBlock
1288
- "inlined in the Compiler"
1289
- ^anotherBlock value
1290
- !
949
+ negative
950
+ "Answer whether the receiver is mathematically negative."
1291
951
 
1292
- isNil
1293
- ^true
952
+ ^ self < 0
1294
953
  !
1295
954
 
1296
- notNil
1297
- ^false
1298
- ! !
955
+ odd
956
+ ^ self even not
957
+ !
1299
958
 
1300
- !UndefinedObject class methodsFor: 'instance creation'!
959
+ positive
960
+ "Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
1301
961
 
1302
- new
1303
- self error: 'You cannot create new instances of UndefinedObject. Use nil'
962
+ ^ self >= 0
1304
963
  ! !
1305
964
 
1306
- Object subclass: #Date
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
- Date wraps the `Date()` JavaScript constructor, and Smalltalk date objects are JavaScript date objects.!
967
+ clearInterval
968
+ <clearInterval(Number(self))>
969
+ !
1314
970
 
1315
- !Date methodsFor: 'accessing'!
971
+ clearTimeout
972
+ <clearTimeout(Number(self))>
973
+ ! !
1316
974
 
1317
- year
1318
- <return self.getFullYear()>
1319
- !
975
+ !Number class methodsFor: 'instance creation'!
1320
976
 
1321
- month
1322
- <return self.getMonth() + 1>
1323
- !
977
+ pi
978
+ <return Math.PI>
979
+ ! !
1324
980
 
1325
- month: aNumber
1326
- <self.setMonth(aNumber - 1)>
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
- day
1330
- ^self dayOfWeek
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
- dayOfWeek
1334
- <return self.getDay() + 1>
1335
- !
990
+ Smalltalk current packageAt: 'Kernel'
1336
991
 
1337
- dayOfWeek: aNumber
1338
- <return self.setDay(aNumber - 1)>
1339
- !
992
+ ...but you can also use:
1340
993
 
1341
- day: aNumber
1342
- self day: aNumber
1343
- !
994
+ Package named: 'Kernel'
1344
995
 
1345
- year: aNumber
1346
- <self.setFullYear(aNumber)>
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
- dayOfMonth
1350
- <return self.getDate()>
1351
- !
1000
+ You can fetch a package from the server:
1352
1001
 
1353
- dayOfMonth: aNumber
1354
- <self.setDate(aNumber)>
1355
- !
1002
+ Package fetch: 'Additional-Examples'!
1356
1003
 
1357
- time
1358
- <return self.getTime()>
1004
+ !Package methodsFor: 'accessing'!
1005
+
1006
+ commitPathJs
1007
+ ^ commitPathJs ifNil: [self class defaultCommitPathJs]
1359
1008
  !
1360
1009
 
1361
- time: aNumber
1362
- <self.setTime(aNumber)>
1010
+ commitPathJs: aString
1011
+ commitPathJs := aString
1363
1012
  !
1364
1013
 
1365
- hours: aNumber
1366
- <self.setHours(aNumber)>
1014
+ commitPathSt
1015
+ ^ commitPathSt ifNil: [self class defaultCommitPathSt]
1367
1016
  !
1368
1017
 
1369
- minutes: aNumber
1370
- <self.setMinutes(aNumber)>
1018
+ commitPathSt: aString
1019
+ commitPathSt := aString
1371
1020
  !
1372
1021
 
1373
- seconds: aNumber
1374
- <self.setSeconds(aNumber)>
1022
+ dependencies
1023
+ ^self propertyAt: 'dependencies' ifAbsent: [#()]
1375
1024
  !
1376
1025
 
1377
- milliseconds: aNumber
1378
- <self.setMilliseconds(aNumber)>
1026
+ dependencies: anArray
1027
+ ^self propertyAt: 'dependencies' put: anArray
1379
1028
  !
1380
1029
 
1381
- hours
1382
- <return self.getHours()>
1030
+ name
1031
+ <return self.pkgName>
1383
1032
  !
1384
1033
 
1385
- minutes
1386
- <return self.getMinutes()>
1034
+ name: aString
1035
+ <self.pkgName = aString>
1387
1036
  !
1388
1037
 
1389
- seconds
1390
- <return self.getSeconds()>
1038
+ properties
1039
+ ^Smalltalk current readJSObject: (self basicAt: 'properties')
1391
1040
  !
1392
1041
 
1393
- milliseconds
1394
- <return self.getMilliseconds()>
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
- !Date methodsFor: 'arithmetic'!
1053
+ !Package methodsFor: 'classes'!
1398
1054
 
1399
- - aDate
1400
- <return self - aDate>
1055
+ classes
1056
+ "We need to do a reverse scan."
1057
+ ^Smalltalk current classes select: [:c | c package == self]
1401
1058
  !
1402
1059
 
1403
- + aDate
1404
- <return self + aDate>
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
- !Date methodsFor: 'comparing'!
1066
+ !Package methodsFor: 'printing'!
1408
1067
 
1409
- < aDate
1410
- <return self < aDate>
1411
- !
1068
+ printString
1069
+ ^self name
1070
+ ! !
1412
1071
 
1413
- > aDate
1414
- <return self >> aDate>
1072
+ !Package methodsFor: 'private'!
1073
+
1074
+ jsProperties
1075
+ <return self.properties>
1415
1076
  !
1416
1077
 
1417
- <= aDate
1418
- <return self <= aDate>
1078
+ jsProperties: aJSObject
1079
+ <return self.properties = aJSObject>
1419
1080
  !
1420
1081
 
1421
- >= aDate
1422
- <return self >>= aDate>
1082
+ propertiesAsJSON
1083
+ <return JSON.stringify(self.properties)>
1423
1084
  ! !
1424
1085
 
1425
- !Date methodsFor: 'converting'!
1426
-
1427
- asString
1428
- <return self.toString()>
1429
- !
1086
+ !Package methodsFor: 'properties'!
1430
1087
 
1431
- asMilliseconds
1432
- ^self time
1433
- !
1088
+ propertyAt: key
1434
1089
 
1435
- asDateString
1436
- <return self.toDateString()>
1090
+ <return self.properties[key]>
1437
1091
  !
1438
1092
 
1439
- asTimeString
1440
- <return self.toTimeString()>
1441
- !
1093
+ propertyAt: key ifAbsent: block
1442
1094
 
1443
- asLocaleString
1444
- <return self.toLocaleString()>
1095
+ ^(self propertyAt: key) ifNil: [block value]
1445
1096
  !
1446
1097
 
1447
- asNumber
1448
- ^self asMilliseconds
1449
- ! !
1450
-
1451
- !Date methodsFor: 'printing'!
1098
+ propertyAt: key put: value
1452
1099
 
1453
- printString
1454
- ^self asString
1100
+ <return self.properties[key] = value>
1455
1101
  ! !
1456
1102
 
1457
- !Date class methodsFor: 'instance creation'!
1458
-
1459
- new: anObject
1460
- <return new Date(anObject)>
1461
- !
1103
+ Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
1462
1104
 
1463
- fromString: aString
1464
- "Example: Date fromString('2011/04/15 00:00:00')"
1465
- ^self new: aString
1466
- !
1105
+ !Package class methodsFor: 'commit paths'!
1467
1106
 
1468
- fromSeconds: aNumber
1469
- ^self fromMilliseconds: aNumber * 1000
1107
+ defaultCommitPathJs
1108
+ ^ defaultCommitPathJs ifNil: [ defaultCommitPathJs := 'js']
1470
1109
  !
1471
1110
 
1472
- fromMilliseconds: aNumber
1473
- ^self new: aNumber
1111
+ defaultCommitPathJs: aString
1112
+ defaultCommitPathJs := aString
1474
1113
  !
1475
1114
 
1476
- today
1477
- ^self new
1115
+ defaultCommitPathSt
1116
+ ^ defaultCommitPathSt ifNil: [ defaultCommitPathSt := 'st']
1478
1117
  !
1479
1118
 
1480
- now
1481
- ^self today
1119
+ defaultCommitPathSt: aString
1120
+ defaultCommitPathSt := aString
1482
1121
  !
1483
1122
 
1484
- millisecondsToRun: aBlock
1485
- | t |
1486
- t := Date now.
1487
- aBlock value.
1488
- ^Date now - t
1123
+ resetCommitPaths
1124
+ defaultCommitPathJs := nil.
1125
+ defaultCommitPathSt := nil.
1489
1126
  ! !
1490
1127
 
1491
- Object subclass: #JSObjectProxy
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
- jsObject: aJSObject
1520
- jsObject := aJSObject
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
- jsObject
1524
- ^jsObject
1137
+ fetch: aPackageName
1138
+ self fetch: aPackageName prefix: self defaultCommitPathJs, '/'
1525
1139
  !
1526
1140
 
1527
- at: aSymbol
1528
- | attr |
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
- at: aSymbol put: anObject
1534
- | attr |
1535
- attr := aSymbol asString.
1536
- <self['@jsObject'][attr] = anObject>
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
- !JSObjectProxy methodsFor: 'proxy'!
1151
+ !Package class methodsFor: 'not yet classified'!
1540
1152
 
1541
- printString
1542
- ^self jsObject toString
1543
- !
1153
+ named: aPackageName
1544
1154
 
1545
- inspectOn: anInspector
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
- doesNotUnderstand: aMessage
1557
- | obj selector jsSelector arguments |
1558
- obj := self jsObject.
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
- !JSObjectProxy class methodsFor: 'instance creation'!
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
- on: aJSObject
1569
- ^self new
1570
- jsObject: aJSObject;
1571
- yourself
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
- category: 'Kernel-Objects'!
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
- category: 'Kernel-Objects'!
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
+