~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/rpython/callparse.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
6
 
 
7
class CallPatternTooComplex(TyperError):
 
8
    pass
 
9
 
 
10
 
 
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()]
 
14
 
 
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())
 
19
    else:
 
20
        return lltype.Void
 
21
 
 
22
def getsig(rtyper, graph):
 
23
    """Return the complete 'signature' of the graph."""
 
24
    return (graph.signature,
 
25
            graph.defaults,
 
26
            getrinputs(rtyper, graph),
 
27
            getrresult(rtyper, graph))
 
28
 
 
29
def callparse(rtyper, graph, hop, opname, r_self=None):
 
30
    """Parse the arguments of 'hop' when calling the given 'graph'.
 
31
    """
 
32
    rinputs = getrinputs(rtyper, graph)
 
33
    space = RPythonCallsSpace()
 
34
    def args_h(start):
 
35
        return [VarHolder(i, hop.args_s[i])
 
36
                        for i in range(start, hop.nb_args)]
 
37
    if r_self is None:
 
38
        start = 1
 
39
    else:
 
40
        start = 0
 
41
        rinputs[0] = r_self
 
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
 
47
                args_h(start+1))
 
48
    # parse the arguments according to the function we are calling
 
49
    signature = graph.signature
 
50
    defs_h = []
 
51
    if graph.defaults:
 
52
        for x in graph.defaults:
 
53
            defs_h.append(ConstHolder(x))
 
54
    try:
 
55
        holders = arguments.match_signature(signature, defs_h)
 
56
    except ArgErr, e:
 
57
        raise TyperError, "signature mismatch: %s" % e.getmsg(graph.name)
 
58
 
 
59
    assert len(holders) == len(rinputs), "argument parsing mismatch"
 
60
    vlist = []
 
61
    for h,r in zip(holders, rinputs):
 
62
        v = h.emit(r, hop)
 
63
        vlist.append(v)
 
64
    return vlist
 
65
 
 
66
 
 
67
class Holder(object):
 
68
 
 
69
    def is_tuple(self):
 
70
        return False
 
71
 
 
72
    def emit(self, repr, hop):
 
73
        try:
 
74
            cache = self._cache
 
75
        except AttributeError:
 
76
            cache = self._cache = {}
 
77
        try:
 
78
            return cache[repr]
 
79
        except KeyError:
 
80
            v = self._emit(repr, hop)
 
81
            cache[repr] = v
 
82
            return v
 
83
    
 
84
 
 
85
class VarHolder(Holder):
 
86
 
 
87
    def __init__(self, num, s_obj):
 
88
        self.num = num
 
89
        self.s_obj = s_obj
 
90
 
 
91
    def is_tuple(self):
 
92
        return isinstance(self.s_obj, annmodel.SomeTuple)
 
93
 
 
94
    def items(self):
 
95
        assert self.is_tuple()
 
96
        n = len(self.s_obj.items)
 
97
        return tuple([ItemHolder(self, i) for i in range(n)])
 
98
        
 
99
    def _emit(self, repr, hop):
 
100
        return hop.inputarg(repr, arg=self.num)
 
101
 
 
102
    def access(self, hop):
 
103
        repr = hop.args_r[self.num]
 
104
        return repr, self.emit(repr, hop)
 
105
 
 
106
class ConstHolder(Holder):
 
107
    def __init__(self, value):
 
108
        self.value = value
 
109
 
 
110
    def is_tuple(self):
 
111
        return type(self.value) is tuple
 
112
 
 
113
    def items(self):
 
114
        assert self.is_tuple()
 
115
        return self.value
 
116
 
 
117
    def _emit(self, repr, hop):
 
118
        return hop.inputconst(repr, self.value)
 
119
 
 
120
 
 
121
class NewTupleHolder(Holder):
 
122
    def __new__(cls, holders):
 
123
        for h in holders:
 
124
            if not isinstance(h, ItemHolder) or not h.holder == holders[0].holder:
 
125
                break
 
126
        else:
 
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)
 
131
        return inst
 
132
 
 
133
    def is_tuple(self):
 
134
        return True
 
135
 
 
136
    def items(self):
 
137
        return self.holders
 
138
 
 
139
    def _emit(self, repr, hop):
 
140
        assert isinstance(repr, rtuple.AbstractTupleRepr)
 
141
        tupleitems_v = []
 
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)
 
146
        return vtuple
 
147
 
 
148
 
 
149
class ItemHolder(Holder):
 
150
    def __init__(self, holder, index):
 
151
        self.holder = holder
 
152
        self.index = index
 
153
 
 
154
    def _emit(self, repr, hop):
 
155
        index = self.index
 
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)
 
159
 
 
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.
 
165
    """
 
166
    w_tuple = NewTupleHolder
 
167
    def newtuple(self, items):
 
168
        return NewTupleHolder(items)
 
169
 
 
170
    def newdict(self):
 
171
        raise CallPatternTooComplex, "'**' argument"
 
172
 
 
173
    def unpackiterable(self, it, expected_length=None):
 
174
        if it.is_tuple():
 
175
            items = it.items()
 
176
            if (expected_length is not None and
 
177
                expected_length != len(items)):
 
178
                raise ValueError
 
179
            return items
 
180
        raise CallPatternTooComplex, "'*' argument must be a tuple"
 
181
 
 
182
    def is_w(self, one, other):
 
183
        return one is other
 
184
 
 
185
    def type(self, item):
 
186
        return type(item)
 
187