Skip to content
Permalink
Newer
Older
100644 651 lines (560 sloc) 17.7 KB
Sep 5, 2014
1
;(function($B){
2
3
eval($B.InjectBuiltins())
Sep 5, 2014
5
var $ObjectDict = _b_.object.$dict
6
Sep 5, 2014
9
// dictionary
10
function $DictClass($keys,$values){
11
this.iter = null
12
this.__class__ = $DictDict
13
$DictDict.clear(this)
14
15
for (var i = 0; i < $keys.length; ++i) {
16
$DictDict.__setitem__($keys[i], $values[i])
17
}
18
}
19
20
dummy = {}
21
22
// can either grow or shrink depending on actual used items
23
var $grow_dict = function(self) {
24
var new_size = $DICT_MINSIZE
25
var target_size = (self.$used < 50000? 2 : 4) * self.$used
26
while (new_size < target_size) {
27
new_size <<= 1
28
}
29
var new_data = Array($DICT_MINSIZE)
30
try {
31
var ig = new $item_generator(self)
32
while(1) {
33
var itm = ig.next()
34
var bucket = $find_empty(itm[0], new_size, new_data)
35
new_data[bucket] = itm
36
}
37
} catch (err) {
38
if (err.__name__ !== "StopIteration") { throw err } else { $B.$pop_exc() }
39
}
40
self.$data = new_data
41
self.$fill = self.$used
42
self.$size = new_size
43
}
44
45
var $lookup_key = function(self, key) {
46
eq = _b_.getattr(key, "__eq__")
47
size = self.$size
48
data = self.$data
49
bucket = Math.abs(_b_.hash(key) % size)
50
val = data[bucket]
51
while (val !== undefined) {
52
if (val === dummy) {
53
bucket = $next_probe(bucket, size)
54
} else {
55
k_val = val[0] // [key, value]
56
if (eq(k_val)) {
57
return bucket
58
} else {
59
bucket = $next_probe(bucket, size)
60
}
61
}
62
val = data[bucket]
63
}
64
self.$empty_bucket = bucket
65
66
return undefined
67
}
68
69
var $find_empty = function(key, size, data) {
70
bucket = Math.abs(hash(key) % size)
71
val = data[bucket]
72
while (val !== undefined) {
73
bucket = $next_probe(bucket, size)
74
val = data[bucket]
75
}
76
return bucket
77
}
78
79
var $next_probe = function(i, size) {
80
return ((i * 5) + 1) % size
Sep 5, 2014
81
}
82
83
var $DictDict = {__class__:$B.$type,
84
__name__ : 'dict',
85
$native:true,
86
__dir__:$ObjectDict.__dir__
Sep 5, 2014
87
}
88
89
var $key_iterator = function(d) {
90
this.d = d
91
this.current = 0
92
this.iter = new $item_generator(d)
93
}
94
$key_iterator.prototype.length = function() { return this.iter.length }
95
$key_iterator.prototype.next = function() { return this.iter.next()[0] }
96
97
var $value_iterator = function(d) {
98
this.d = d
99
this.current = 0
100
this.iter = new $item_generator(d)
101
}
102
$value_iterator.prototype.length = function() { return this.iter.length }
103
$value_iterator.prototype.next = function() { return this.iter.next()[1] }
104
105
var $item_generator = function(d) {
106
this.i = 0
107
this.data = d.$data
108
this.size = d.$size
109
this.used = d.$used
110
this.length=0
111
112
this.items=[]
113
for (var k in d.$numeric_dict) {
114
this.items.push([parseFloat(k), d.$numeric_dict[k]])
115
}
116
117
for (var k in d.$string_dict) {
118
this.items.push([k, d.$string_dict[k]])
119
}
120
121
for (var i=0; i < this.data.length; i++) {
122
var _v=this.data[i]
123
if (_v === undefined || _v === dummy) continue
124
this.items.push(_v)
125
}
126
this.length=this.items.length
127
}
128
$item_generator.prototype.next = function() {
129
if (this.i < this.items.length) {
130
return this.items[this.i++]
131
}
132
throw _b_.StopIteration("StopIteration")
133
}
134
$item_generator.prototype.as_list = function() {
135
return this.items
136
}
137
138
var $item_iterator = function(d) {
139
this.d = d
140
this.current = 0
141
this.iter = new $item_generator(d)
142
}
143
$item_iterator.prototype.length = function() {return this.iter.items.length }
144
$item_iterator.prototype.next = function() { return _b_.tuple(this.iter.next()) }
145
146
var $copy_dict = function(left, right) {
147
var gen = new $item_generator(right)
148
try {
149
while(1) {
150
var item = gen.next()
151
$DictDict.__setitem__(left, item[0], item[1])
152
}
153
} catch (err) {
154
if (err.__name__ !== "StopIteration") { throw err } else { $B.$pop_exc() }
155
}
156
}
157
158
$iterator_wrapper = function(items,klass){
159
var res = {
160
__class__:klass,
161
__iter__:function(){items.iter.i=0; return res},
162
__len__:function(){return items.length()},
163
__next__:function(){
164
//if (items.length() !== items.iter.used) {
165
// throw _b_.RuntimeError("dictionary changed size during iteration")
166
//}
168
//return items[counter++]
170
//__repr__:function(){return "<"+klass.__name__+" object>"},
171
//counter:0
172
}
173
res.__str__ = res.toString = res.__repr__
174
return res
175
}
176
178
var $dict_keysDict = $B.$iterator_class('dict_keys')
179
180
$DictDict.keys = function(self){
181
if (arguments.length > 1) {
182
var _len=arguments.length - 1
183
var _msg="keys() takes no arguments ("+_len+" given)"
184
throw _b_.TypeError(_msg)
185
}
186
return $iterator_wrapper(new $key_iterator(self),$dict_keysDict)
187
}
188
189
var $dict_valuesDict = $B.$iterator_class('dict_values')
190
191
$DictDict.values = function(self){
192
if (arguments.length > 1) {
193
var _len=arguments.length - 1
194
var _msg="values() takes no arguments ("+_len+" given)"
195
throw _b_.TypeError(_msg)
196
}
197
return $iterator_wrapper(new $value_iterator(self), $dict_valuesDict)
198
}
199
200
$DictDict.__bool__ = function (self) {return $DictDict.__len__(self) > 0}
Sep 5, 2014
201
202
$DictDict.__contains__ = function(self,item){
203
if(self.$jsobj) return self.$jsobj[item]!==undefined
204
switch(typeof item) {
205
case 'string':
206
return self.$string_dict[item] !==undefined
207
case 'number':
208
return self.$numeric_dict[item] !==undefined
210
return $lookup_key(self, item) !== undefined
Sep 5, 2014
211
}
212
213
$DictDict.__delitem__ = function(self,arg){
214
switch(typeof arg) {
215
case 'string':
216
if (self.$string_dict[arg] === undefined) throw KeyError(_b_.str(arg))
217
delete self.$string_dict[arg]
218
if (self.$jsobj) delete self.$jsobj[arg]
219
return
220
case 'number':
221
if (self.$numeric_dict[arg] === undefined) throw KeyError(_b_.str(arg))
222
delete self.$numeric_dict[arg]
223
if (self.$jsobj) delete self.$jsobj[arg]
224
return
225
}
226
// go with defaults
227
228
var bucket = $lookup_key(self, arg)
229
if (bucket === undefined) throw KeyError(_b_.str(arg))
230
self.$data[bucket] = dummy
231
--self.$used
232
233
if(self.$jsobj) delete self.$jsobj[arg]
Sep 5, 2014
234
}
235
236
$DictDict.__eq__ = function(self,other){
237
if(other===undefined){ // compare self to class "dict"
238
return self===dict
239
}
240
if(!isinstance(other,dict)) return false
241
242
if ($DictDict.__len__(self) != $DictDict.__len__(other)) return false
243
244
var gen = new $item_generator(self)
245
var keys1=[]
246
try {
247
while(1) keys1.push(gen.next()[0])
248
} catch (err) {
249
Sep 5, 2014
250
}
251
252
for (var i=0; i < keys1.length; i++) {
253
var key=keys1[i]
254
if (!$DictDict.__contains__(other, key)) return false
255
var v1=$DictDict.__getitem__(self, key)
256
var v2=$DictDict.__getitem__(other, key)
257
if (!getattr(v1, '__eq__')(v2)) return false
258
}
259
260
return true
Sep 5, 2014
261
}
262
263
$DictDict.__getitem__ = function(self,arg){
264
if(self.$jsobj && self.$jsobj[arg] !== undefined) return self.$jsobj[arg]
265
266
switch(typeof arg) {
267
case 'string':
268
if (self.$string_dict[arg] !== undefined) return self.$string_dict[arg]
269
break
270
case 'number':
271
if (self.$numeric_dict[arg] !== undefined) return self.$numeric_dict[arg]
272
}
273
// since the key is more complex use 'default' method of getting item
274
275
var bucket = $lookup_key(self, arg)
276
if (bucket !== undefined) return self.$data[bucket][1]
277
278
if(hasattr(self, '__missing__')) return getattr(self, '__missing__')(arg)
279
Sep 5, 2014
280
throw KeyError(_b_.str(arg))
281
}
282
283
$DictDict.__hash__ = function(self) {
284
if (self === undefined) {
285
return $DictDict.__hashvalue__ || $B.$py_next_hash-- // for hash of dict type (not instance of dict)
286
}
287
throw _b_.TypeError("unhashable type: 'dict'");
288
}
Sep 5, 2014
289
290
$DictDict.__init__ = function(self){
291
var args = []
292
for(var i=1;i<arguments.length;i++){args.push(arguments[i])}
293
$DictDict.clear(self)
294
switch(args.length) {
295
case 0:
296
return
297
case 1:
Sep 5, 2014
298
var obj = args[0]
299
if(isinstance(obj,dict)){
Sep 5, 2014
301
return
302
}
Sep 5, 2014
304
if(obj.__class__===$B.JSObject.$dict){
305
// convert a JSObject into a Python dictionary
306
for(var attr in obj.js){
307
$DictDict.__setitem__(self,attr,obj.js[attr])
Sep 5, 2014
308
}
309
// Attribute $jsobj is used to update the original JS object
310
// when the dictionary is modified
Sep 5, 2014
312
return
313
}
Sep 5, 2014
316
var $ns=$B.$MakeArgs('dict',args,[],[],'args','kw')
317
var args = $ns['args']
318
var kw = $ns['kw']
Sep 5, 2014
321
if(isinstance(args[0],dict)){
Sep 5, 2014
323
return
324
}
Sep 5, 2014
326
// format dict([(k1,v1),(k2,v2)...])
327
var iterable = iter(args[0])
328
while(1){
329
try{
330
var elt = next(iterable)
331
var key = getattr(elt,'__getitem__')(0)
332
var value = getattr(elt,'__getitem__')(1)
333
$DictDict.__setitem__(self, key, value)
Sep 5, 2014
334
}catch(err){
335
if(err.__name__==='StopIteration'){$B.$pop_exc();break}
336
throw err
337
}
338
}
340
if($DictDict.__len__(kw) > 0) $copy_dict(self, kw)
Sep 5, 2014
341
}
342
343
var $dict_iterator = $B.$iterator_class('dict iterator')
344
$DictDict.__iter__ = function(self) {
345
return $DictDict.keys(self)
Sep 5, 2014
346
}
347
348
$DictDict.__len__ = function(self) {
349
var _num_len=0, _str_len=0
350
351
for (var k in self.$numeric_dict) _num_len++
352
for (var k in self.$string_dict) _str_len++
353
354
return self.$used + _num_len + _str_len
355
}
Sep 5, 2014
356
357
$DictDict.__mro__ = [$DictDict,$ObjectDict]
358
359
$DictDict.__ne__ = function(self,other){return !$DictDict.__eq__(self,other)}
360
361
$DictDict.__next__ = function(self){
363
self.$iter = new $item_generator(self) //.$data)
364
}
365
try {
366
return self.$iter.next()
367
} catch (err) {
368
if (err.__name__ !== "StopIteration") { throw err } else { $B.$pop_exc() }
Sep 5, 2014
369
}
370
}
371
372
$DictDict.__repr__ = function(self){
373
if(self===undefined) return "<class 'dict'>"
374
var _objs=[self] // used to elimate recursion
Sep 5, 2014
375
var res=[]
376
var items = new $item_generator(self).as_list()
377
for (var i=0; i < items.length; i++) {
378
var itm = items[i]
Jan 18, 2015
379
if (_objs.indexOf(itm[1]) > -1 && _b_.isinstance(itm[1], [_b_.dict,_b_.list,_b_.set, _b_.tuple])) {
380
var value='?'+_b_.type(itm[1])
381
if(isinstance(itm[1], dict)) value='{...}'
382
res.push(repr(itm[0])+': '+ value)
383
} else {
Jan 18, 2015
384
if (_objs.indexOf(itm[1]) == -1) _objs.push(itm[1])
385
res.push(repr(itm[0])+': '+repr(itm[1]))
386
}
Sep 5, 2014
387
}
388
return '{'+ res.join(', ') +'}'
Sep 5, 2014
389
}
390
391
$DictDict.__setitem__ = function(self,key,value){
392
switch(typeof key) {
393
case 'string':
394
self.$string_dict[key]=value
395
if(self.$jsobj) self.$jsobj[key]=value
396
return
397
case 'number':
398
self.$numeric_dict[key]=value
399
if(self.$jsobj) self.$jsobj[key]=value
400
return
401
}
402
403
// if we got here the key is more complex, use default method
404
405
// if adding new item would invoke a grow...
406
if (self.$fill + 1 > self.$size * 3 / 4) {
407
$grow_dict(self)
408
}
409
410
var bucket = $lookup_key(self, key)
411
if (bucket === undefined) {
412
bucket = self.$empty_bucket
413
++self.$fill
414
++self.$used
Sep 5, 2014
415
}
416
self.$data[bucket] = [key, value]
417
Sep 5, 2014
418
if(self.$jsobj) self.$jsobj[key]=value
419
}
420
421
$DictDict.__str__ = $DictDict.__repr__
422
423
// add "reflected" methods
424
$B.make_rmethods($DictDict)
425
426
$DictDict.clear = function(self){
427
// Remove all items from the dictionary.
428
self.$data = Array($DICT_MINSIZE)
429
self.$size = $DICT_MINSIZE
430
self.$fill = 0
431
self.$used = 0
432
433
self.$numeric_dict={}
434
self.$string_dict={}
435
Sep 5, 2014
436
if(self.$jsobj) self.$jsobj={}
437
}
438
439
$DictDict.copy = function(self){
440
// Return a shallow copy of the dictionary
441
var res = _b_.dict()
442
$copy_dict(res, self)
Sep 5, 2014
443
return res
444
}
445
446
$DictDict.get = function(self, key, _default){
447
if (_default === undefined) _default=None
448
switch(typeof key) {
449
case 'string':
450
return self.$string_dict[key] || _default
451
case 'number':
452
return self.$numeric_dict[key] || _default
Sep 5, 2014
453
}
454
455
var bucket = $lookup_key(self, key)
456
if(bucket !== undefined) return self.$data[bucket][1]
457
if(_default!==undefined) return _default
458
return None
Sep 5, 2014
459
}
460
461
var $dict_itemsDict = $B.$iterator_class('dict_items')
Sep 5, 2014
462
463
$DictDict.items = function(self){
464
if (arguments.length > 1) {
465
var _len=arguments.length - 1
466
var _msg="items() takes no arguments ("+_len+" given)"
467
throw _b_.TypeError(_msg)
468
}
469
return $iterator_wrapper(new $item_iterator(self), $dict_itemsDict)
Sep 5, 2014
470
}
471
472
$DictDict.fromkeys = function(keys,value){
Sep 5, 2014
473
// class method
474
if(value===undefined) value=None
Sep 5, 2014
475
var res = dict()
476
var keys_iter = _b_.iter(keys)
477
while(1){
478
try{
479
var key = _b_.next(keys_iter)
480
$DictDict.__setitem__(res,key,value)
481
}catch(err){
482
if($B.is_exc(err,[_b_.StopIteration])){
483
$B.$pop_exc()
484
return res
485
}
486
throw err
487
}
488
}
489
}
490
491
$DictDict.pop = function(self,key,_default){
492
try{
493
var res = $DictDict.__getitem__(self,key)
494
$DictDict.__delitem__(self,key)
495
return res
496
}catch(err){
497
$B.$pop_exc()
498
if(err.__name__==='KeyError'){
499
if(_default!==undefined) return _default
500
throw err
501
}
502
throw err
503
}
504
}
505
506
$DictDict.popitem = function(self){
507
try{
508
var itm = new $item_iterator(self).next()
509
$DictDict.__delitem__(self,itm[0])
510
return _b_.tuple(itm)
511
}catch(err) {
512
if (err.__name__ == "StopIteration") {
513
$B.$pop_exc()
514
throw KeyError("'popitem(): dictionary is empty'")
515
}
516
}
Sep 5, 2014
517
}
518
519
$DictDict.setdefault = function(self,key,_default){
520
try{return $DictDict.__getitem__(self,key)}
521
catch(err){
522
if(_default===undefined) _default=None
523
$DictDict.__setitem__(self,key,_default)
524
return _default
525
}
526
}
527
528
$DictDict.update = function(self){
529
var params = []
530
for(var i=1;i<arguments.length;i++){params.push(arguments[i])}
Sep 5, 2014
531
var $ns=$B.$MakeArgs('$DictDict.update',params,[],[],'args','kw')
532
var args = $ns['args']
533
if(args.length>0) {
534
var o=args[0]
535
if (isinstance(o,dict)){
536
$copy_dict(self, o)
537
} else if (hasattr(o, '__getitem__') && hasattr(o, 'keys')) {
538
var _keys=_b_.list(getattr(o, 'keys')())
539
for (var i=0; i < _keys.length; i++) {
540
var _value = getattr(o, '__getitem__')(_keys[i])
541
$DictDict.__setitem__(self, _keys[i], _value)
542
}
543
}
Sep 5, 2014
544
}
545
var kw = $ns['kw']
Sep 5, 2014
547
}
548
549
function dict(){
550
var res = {__class__:$DictDict}
551
// apply __init__ with arguments of dict()
552
var args = [res]
553
for(var i=0, _len_i = arguments.length; i < _len_i;i++){args.push(arguments[i])}
Sep 5, 2014
554
$DictDict.__init__.apply(null,args)
555
return res
556
}
Sep 5, 2014
558
$B.$dict = dict // used for dict literals : "x={}" is translated to "x=__BRYTHON__.$dict()",
559
// not to "x=dict()"
560
// otherwise this would fail :
561
// def foo(dict=None):
562
// x = {}
563
// because inside the function, 'dict' has beeen set to the
564
// value of argument 'dict'
565
dict.__class__ = $B.$factory
566
dict.$dict = $DictDict
567
$DictDict.$factory = dict
568
$DictDict.__new__ = $B.$__new__(dict)
569
570
_b_.dict = dict
572
// following are used for faster access elsewhere
573
$B.$dict_iterator = function(d) { return new $item_generator(d) }
574
$B.$dict_length = $DictDict.__len__
575
$B.$dict_getitem = $DictDict.__getitem__
576
$B.$dict_get = $DictDict.get
577
$B.$dict_set = $DictDict.__setitem__
578
$B.$dict_contains = $DictDict.__contains__
579
$B.$dict_items = function(d) { return new $item_generator(d).as_list() }
580
$B.$copy_dict = $copy_dict // copy from right to left
581
$B.$dict_get_copy = $DictDict.copy // return a shallow copy
582
583
// Class used for attribute __dict__ of objects
584
585
$ObjDictDict = {__class__:$B.$type,__name__:'obj_dict'}
586
$ObjDictDict.__mro__ = [$ObjDictDict, $DictDict, $ObjectDict]
587
588
$ObjDictDict.__delitem__ = function(self, key){
589
$DictDict.__delitem__(self, key)
590
delete self.$obj[key]
591
}
592
593
$ObjDictDict.__setitem__ = function(self, key, value){
594
$DictDict.__setitem__(self, key, value)
595
self.$obj[key] = value
596
}
597
598
$ObjDictDict.clear = function(self){
599
$DictDict.clear(self)
600
for(var key in self.$obj){delete self.$obj[key]}
601
}
602
603
$ObjDictDict.pop = function(self, key, _default){
604
$DictDict.pop(self, key, _default)
605
delete self.$obj[key]
606
return key
607
}
608
609
$ObjDictDict.popitem = function(self){
610
var res = $DictDict.popitem(self) // tuple
611
var key = res[0]
612
delete self.$obj[key]
613
return res
614
}
615
616
$ObjDictDict.update = function(self){
617
$DictDict.update.apply(null, arguments)
618
// Update attributes of underlying object by iterating on self.items()
619
var it = $DictDict.items(self)
620
while(true){
621
try{
622
var item = next(it)
623
self.$obj[item[0]] = item[1]
624
}catch(err){
625
if($B.is_exc(err,[_b_.StopIteration])){
626
$B.$pop_exc();return
627
}
628
throw err
629
}
630
}
634
// Function called to get attribute "__dict__" of an object
635
if(obj.__class__===$B.$factory){return obj.$dict.__dict__}
636
var res = {__class__:$ObjDictDict,$obj:obj}
637
$DictDict.clear(res)
638
for(var attr in obj){
639
if(attr.charAt(0)!='$'){
640
$DictDict.__setitem__(res, attr, obj[attr])
641
}
642
}
643
return res
644
}
645
obj_dict.$dict = $ObjDictDict
646
obj_dict.__class__ = $B.$factory
647
$ObjDictDict.$factory = obj_dict
648
649
$B.obj_dict = obj_dict
650
Sep 5, 2014
651
})(__BRYTHON__)