1
from pypy.interpreter.argument import Arguments, ArgErr
2
from pypy.annotation import model as annmodel
3
from pypy.rpython import rtuple
4
from pypy.rpython.error import TyperError
5
from pypy.rpython.lltypesystem import lltype
7
class CallPatternTooComplex(TyperError):
11
def getrinputs(rtyper, graph):
12
"""Return the list of reprs of the input arguments to the 'graph'."""
13
return [rtyper.bindingrepr(v) for v in graph.getargs()]
15
def getrresult(rtyper, graph):
16
"""Return the repr of the result variable of the 'graph'."""
17
if graph.getreturnvar() in rtyper.annotator.bindings:
18
return rtyper.bindingrepr(graph.getreturnvar())
22
def getsig(rtyper, graph):
23
"""Return the complete 'signature' of the graph."""
24
return (graph.signature,
26
getrinputs(rtyper, graph),
27
getrresult(rtyper, graph))
29
def callparse(rtyper, graph, hop, opname, r_self=None):
30
"""Parse the arguments of 'hop' when calling the given 'graph'.
32
rinputs = getrinputs(rtyper, graph)
33
space = RPythonCallsSpace()
35
return [VarHolder(i, hop.args_s[i])
36
for i in range(start, hop.nb_args)]
42
if opname == "simple_call":
43
arguments = Arguments(space, args_h(start))
44
elif opname == "call_args":
45
arguments = Arguments.fromshape(space,
46
hop.args_s[start].const, # shape
48
# parse the arguments according to the function we are calling
49
signature = graph.signature
52
for x in graph.defaults:
53
defs_h.append(ConstHolder(x))
55
holders = arguments.match_signature(signature, defs_h)
57
raise TyperError, "signature mismatch: %s" % e.getmsg(graph.name)
59
assert len(holders) == len(rinputs), "argument parsing mismatch"
61
for h,r in zip(holders, rinputs):
72
def emit(self, repr, hop):
75
except AttributeError:
76
cache = self._cache = {}
80
v = self._emit(repr, hop)
85
class VarHolder(Holder):
87
def __init__(self, num, s_obj):
92
return isinstance(self.s_obj, annmodel.SomeTuple)
95
assert self.is_tuple()
96
n = len(self.s_obj.items)
97
return tuple([ItemHolder(self, i) for i in range(n)])
99
def _emit(self, repr, hop):
100
return hop.inputarg(repr, arg=self.num)
102
def access(self, hop):
103
repr = hop.args_r[self.num]
104
return repr, self.emit(repr, hop)
106
class ConstHolder(Holder):
107
def __init__(self, value):
111
return type(self.value) is tuple
114
assert self.is_tuple()
117
def _emit(self, repr, hop):
118
return hop.inputconst(repr, self.value)
121
class NewTupleHolder(Holder):
122
def __new__(cls, holders):
124
if not isinstance(h, ItemHolder) or not h.holder == holders[0].holder:
127
if 0 < len(holders) == len(holders[0].holder.items()):
128
return holders[0].holder
129
inst = Holder.__new__(cls)
130
inst.holders = tuple(holders)
139
def _emit(self, repr, hop):
140
assert isinstance(repr, rtuple.AbstractTupleRepr)
142
for h in self.holders:
143
v = h.emit(repr.items_r[len(tupleitems_v)], hop)
144
tupleitems_v.append(v)
145
vtuple = repr.newtuple(hop.llops, repr, tupleitems_v)
149
class ItemHolder(Holder):
150
def __init__(self, holder, index):
154
def _emit(self, repr, hop):
156
r_tup, v_tuple = self.holder.access(hop)
157
v = r_tup.getitem_internal(hop, v_tuple, index)
158
return hop.llops.convertvar(v, r_tup.items_r[index], repr)
160
# for parsing call arguments
161
class RPythonCallsSpace:
162
"""Pseudo Object Space providing almost no real operation.
163
For the Arguments class: if it really needs other operations, it means
164
that the call pattern is too complex for R-Python.
166
w_tuple = NewTupleHolder
167
def newtuple(self, items):
168
return NewTupleHolder(items)
171
raise CallPatternTooComplex, "'**' argument"
173
def unpackiterable(self, it, expected_length=None):
176
if (expected_length is not None and
177
expected_length != len(items)):
180
raise CallPatternTooComplex, "'*' argument must be a tuple"
182
def is_w(self, one, other):
185
def type(self, item):