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