-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrdict.py
More file actions
148 lines (121 loc) · 6.3 KB
/
rdict.py
File metadata and controls
148 lines (121 loc) · 6.3 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from rpython.annotator import model as annmodel
from rpython.rtyper import rmodel
from rpython.rtyper.lltypesystem import lltype
class __extend__(annmodel.SomeDict):
def get_dict_repr(self):
from rpython.rtyper.lltypesystem.rdict import DictRepr
return DictRepr
def rtyper_makerepr(self, rtyper):
dictkey = self.dictdef.dictkey
dictvalue = self.dictdef.dictvalue
s_key = dictkey.s_value
s_value = dictvalue.s_value
force_non_null = self.dictdef.force_non_null
simple_hash_eq = self.dictdef.simple_hash_eq
if dictkey.custom_eq_hash:
custom_eq_hash = lambda: (rtyper.getrepr(dictkey.s_rdict_eqfn),
rtyper.getrepr(dictkey.s_rdict_hashfn))
else:
custom_eq_hash = None
return self.get_dict_repr()(rtyper, lambda: rtyper.getrepr(s_key),
lambda: rtyper.getrepr(s_value), dictkey, dictvalue,
custom_eq_hash, force_non_null, simple_hash_eq)
def rtyper_makekey(self):
self.dictdef.dictkey .dont_change_any_more = True
self.dictdef.dictvalue.dont_change_any_more = True
return (self.__class__, self.dictdef.dictkey, self.dictdef.dictvalue)
class __extend__(annmodel.SomeOrderedDict):
def get_dict_repr(self):
from rpython.rtyper.lltypesystem.rordereddict import OrderedDictRepr
return OrderedDictRepr
class AbstractDictRepr(rmodel.Repr):
def pickrepr(self, item_repr):
if self.custom_eq_hash:
return item_repr, item_repr
else:
return self._externalvsinternal(self.rtyper, item_repr)
pickkeyrepr = pickrepr
def compact_repr(self):
return 'DictR %s %s' % (self.key_repr.compact_repr(),
self.value_repr.compact_repr())
def recast_value(self, llops, v):
return llops.convertvar(v, self.value_repr, self.external_value_repr)
def recast_key(self, llops, v):
return llops.convertvar(v, self.key_repr, self.external_key_repr)
def rtype_newdict(hop):
hop.inputargs() # no arguments expected
r_dict = hop.r_result
cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
v_result = hop.gendirectcall(r_dict.ll_newdict, cDICT)
return v_result
class AbstractDictIteratorRepr(rmodel.IteratorRepr):
def newiter(self, hop):
v_dict, = hop.inputargs(self.r_dict)
citerptr = hop.inputconst(lltype.Void, self.lowleveltype)
return hop.gendirectcall(self.ll_dictiter, citerptr, v_dict)
def rtype_next(self, hop):
v_iter, = hop.inputargs(self)
# record that we know about these two possible exceptions
hop.has_implicit_exception(StopIteration)
hop.has_implicit_exception(RuntimeError)
hop.exception_is_here()
v_index = hop.gendirectcall(self._ll_dictnext, v_iter)
#
# read 'iter.dict.entries'
DICT = self.lowleveltype.TO.dict
c_dict = hop.inputconst(lltype.Void, 'dict')
v_dict = hop.genop('getfield', [v_iter, c_dict], resulttype=DICT)
ENTRIES = DICT.TO.entries
c_entries = hop.inputconst(lltype.Void, 'entries')
v_entries = hop.genop('getfield', [v_dict, c_entries],
resulttype=ENTRIES)
# call the correct variant_*() method
method = getattr(self, 'variant_' + self.variant)
return method(hop, ENTRIES, v_entries, v_dict, v_index)
def get_tuple_result(self, hop, items_v):
# this allocates the tuple for the result, directly in the function
# where it will be used (likely). This will let it be removed.
if hop.r_result.lowleveltype is lltype.Void:
return hop.inputconst(lltype.Void, None)
c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype.TO)
cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
v_result = hop.genop('malloc', [c1, cflags],
resulttype = hop.r_result.lowleveltype)
for i, v_item in enumerate(items_v):
ITEM = getattr(v_result.concretetype.TO, 'item%d' % i)
if ITEM != v_item.concretetype:
assert isinstance(ITEM, lltype.Ptr)
v_item = hop.genop('cast_pointer', [v_item], resulttype=ITEM)
c_item = hop.inputconst(lltype.Void, 'item%d' % i)
hop.genop('setfield', [v_result, c_item, v_item])
return v_result
def variant_keys(self, hop, ENTRIES, v_entries, v_dict, v_index):
KEY = ENTRIES.TO.OF.key
c_key = hop.inputconst(lltype.Void, 'key')
v_key = hop.genop('getinteriorfield', [v_entries, v_index, c_key],
resulttype=KEY)
return self.r_dict.recast_key(hop.llops, v_key)
variant_reversed = variant_keys
def variant_values(self, hop, ENTRIES, v_entries, v_dict, v_index):
VALUE = ENTRIES.TO.OF.value
c_value = hop.inputconst(lltype.Void, 'value')
v_value = hop.genop('getinteriorfield', [v_entries,v_index,c_value],
resulttype=VALUE)
return self.r_dict.recast_value(hop.llops, v_value)
def variant_items(self, hop, ENTRIES, v_entries, v_dict, v_index):
v_key = self.variant_keys(hop, ENTRIES, v_entries, v_dict, v_index)
v_value = self.variant_values(hop, ENTRIES, v_entries, v_dict, v_index)
return self.get_tuple_result(hop, (v_key, v_value))
def variant_hashes(self, hop, ENTRIES, v_entries, v_dict, v_index):
# there is not really a variant 'hashes', but this method is
# convenient for the following variants
return hop.gendirectcall(ENTRIES.TO.entry_hash, v_entries, v_dict, v_index)
def variant_keys_with_hash(self, hop, ENTRIES, v_entries, v_dict, v_index):
v_key = self.variant_keys(hop, ENTRIES, v_entries, v_dict, v_index)
v_hash = self.variant_hashes(hop, ENTRIES, v_entries, v_dict, v_index)
return self.get_tuple_result(hop, (v_key, v_hash))
def variant_items_with_hash(self, hop, ENTRIES, v_entries, v_dict, v_index):
v_key = self.variant_keys(hop, ENTRIES, v_entries, v_dict, v_index)
v_value = self.variant_values(hop, ENTRIES, v_entries, v_dict, v_index)
v_hash = self.variant_hashes(hop, ENTRIES, v_entries, v_dict, v_index)
return self.get_tuple_result(hop, (v_key, v_value, v_hash))