forked from nawalgupta/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictdef.py
More file actions
119 lines (96 loc) · 4.36 KB
/
Copy pathdictdef.py
File metadata and controls
119 lines (96 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from rpython.annotator.model import (
s_ImpossibleValue, SomeInteger, s_Bool, union)
from rpython.annotator.listdef import ListItem
from rpython.rlib.objectmodel import compute_hash
class DictKey(ListItem):
s_rdict_eqfn = s_ImpossibleValue
s_rdict_hashfn = s_ImpossibleValue
def __init__(self, bookkeeper, s_value, is_r_dict=False):
ListItem.__init__(self, bookkeeper, s_value)
self.custom_eq_hash = is_r_dict
def patch(self):
for dictdef in self.itemof:
dictdef.dictkey = self
def merge(self, other):
if self is not other:
assert self.custom_eq_hash == other.custom_eq_hash, (
"mixing plain dictionaries with r_dict()")
ListItem.merge(self, other)
if self.custom_eq_hash:
self.update_rdict_annotations(other.s_rdict_eqfn,
other.s_rdict_hashfn,
other=other)
def generalize(self, s_other_value):
updated = ListItem.generalize(self, s_other_value)
if updated and self.custom_eq_hash:
self.emulate_rdict_calls()
return updated
def update_rdict_annotations(self, s_eqfn, s_hashfn, other=None):
assert self.custom_eq_hash
s_eqfn = union(s_eqfn, self.s_rdict_eqfn)
s_hashfn = union(s_hashfn, self.s_rdict_hashfn)
self.s_rdict_eqfn = s_eqfn
self.s_rdict_hashfn = s_hashfn
self.emulate_rdict_calls(other=other)
def emulate_rdict_calls(self, other=None):
myeq = (self, 'eq')
myhash = (self, 'hash')
if other:
replace_othereq = [(other, 'eq')]
replace_otherhash = [(other, 'hash')]
else:
replace_othereq = replace_otherhash = ()
s_key = self.s_value
def check_eqfn(annotator, graph):
s = annotator.binding(graph.getreturnvar())
assert s_Bool.contains(s), (
"the custom eq function of an r_dict must return a boolean"
" (got %r)" % (s,))
self.bookkeeper.emulate_pbc_call(myeq, self.s_rdict_eqfn, [s_key, s_key],
replace=replace_othereq,
callback = check_eqfn)
def check_hashfn(annotator, graph):
s = annotator.binding(graph.getreturnvar())
assert SomeInteger().contains(s), (
"the custom hash function of an r_dict must return an integer"
" (got %r)" % (s,))
self.bookkeeper.emulate_pbc_call(myhash, self.s_rdict_hashfn, [s_key],
replace=replace_otherhash,
callback = check_hashfn)
class DictValue(ListItem):
def patch(self):
for dictdef in self.itemof:
dictdef.dictvalue = self
class DictDef(object):
"""A dict definition remembers how general the keys and values in that
particular dict have to be. Every dict creation makes a new DictDef,
and the union of two dicts merges the DictKeys and DictValues that each
DictDef stores."""
def __init__(self, bookkeeper, s_key = s_ImpossibleValue,
s_value = s_ImpossibleValue,
is_r_dict = False,
force_non_null = False):
self.dictkey = DictKey(bookkeeper, s_key, is_r_dict)
self.dictkey.itemof[self] = True
self.dictvalue = DictValue(bookkeeper, s_value)
self.dictvalue.itemof[self] = True
self.force_non_null = force_non_null
def read_key(self, position_key):
self.dictkey.read_locations[position_key] = True
return self.dictkey.s_value
def read_value(self, position_key):
self.dictvalue.read_locations[position_key] = True
return self.dictvalue.s_value
def same_as(self, other):
return (self.dictkey is other.dictkey and
self.dictvalue is other.dictvalue)
def union(self, other):
self.dictkey.merge(other.dictkey)
self.dictvalue.merge(other.dictvalue)
return self
def generalize_key(self, s_key):
self.dictkey.generalize(s_key)
def generalize_value(self, s_value):
self.dictvalue.generalize(s_value)
def __repr__(self):
return '<{%r: %r}>' % (self.dictkey.s_value, self.dictvalue.s_value)