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

« back to all changes in this revision

Viewing changes to pypy/rpython/ootypesystem/bltregistry.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
 
 
2
""" External objects registry,
 
3
"""
 
4
 
 
5
from pypy.annotation import model as annmodel
 
6
from pypy.objspace.flow.model import Variable, Constant
 
7
from pypy.rpython.ootypesystem import ootype
 
8
from pypy.annotation.bookkeeper import getbookkeeper
 
9
from pypy.rpython.lltypesystem.lltype import frozendict, isCompatibleType
 
10
from types import MethodType
 
11
from pypy.rpython.extregistry import ExtRegistryEntry
 
12
from pypy.rpython.ootypesystem.extdesc import MethodDesc, ArgDesc
 
13
from pypy.annotation.signature import annotation
 
14
from pypy.annotation.model import unionof
 
15
 
 
16
class CallableEntry(ExtRegistryEntry):
 
17
    _type_ = MethodDesc
 
18
    
 
19
    def compute_annotation(self):
 
20
        bookkeeper = getbookkeeper()
 
21
        args_s = [annotation(i._type) for i in self.instance.args]
 
22
        s_result = annotation(self.instance.result._type)
 
23
        return annmodel.SomeGenericCallable(args=args_s, result=s_result)
 
24
 
 
25
class BasicMetaExternal(type):
 
26
    def _is_compatible(type2):
 
27
        return type(type2) is BasicMetaExternal
 
28
    
 
29
    def __new__(self, _name, _type, _vars):
 
30
        retval = type.__new__(self, _name, _type, _vars)
 
31
        if not retval._methods:
 
32
            retval._methods = {}
 
33
        for name, var in _vars.iteritems():
 
34
            if hasattr(var, '_method'):
 
35
                meth_name, desc = var._method
 
36
                retval._methods[meth_name] = desc
 
37
        return retval
 
38
    
 
39
    _is_compatible = staticmethod(_is_compatible)
 
40
 
 
41
def typeof(val):
 
42
    """ Small wrapper, which tries to resemble example -> python type
 
43
    which can go to annotation path
 
44
    """
 
45
    if isinstance(val, list):
 
46
        return [typeof(val[0])]
 
47
    if isinstance(val, dict):
 
48
        return {typeof(val.keys()[0]):typeof(val.values()[0])}
 
49
    if isinstance(val, tuple):
 
50
        return tuple([typeof(i) for i in val])
 
51
    return type(val)
 
52
 
 
53
def load_dict_args(varnames, defs, args):
 
54
    argcount = len(varnames)
 
55
    assert(argcount < len(defs) + len(args), "Not enough information for describing method")
 
56
           
 
57
    for arg in xrange(1, argcount - len(defs)):
 
58
        assert varnames[arg] in args, "Don't have type for arg %s" % varnames[arg]
 
59
 
 
60
    arg_pass = []
 
61
    start_pos = argcount - len(defs)
 
62
    for arg in xrange(1, argcount):
 
63
        varname = varnames[arg]
 
64
        if varname in args:
 
65
            arg_pass.append((varname, args[varname]))
 
66
        else:
 
67
            arg_pass.append((varname, typeof(defs[arg - start_pos])))
 
68
    return arg_pass
 
69
 
 
70
class BasicExternal(object):
 
71
    __metaclass__ = BasicMetaExternal
 
72
    __self__ = None
 
73
    
 
74
    _fields = {}
 
75
    _methods = {}
 
76
    
 
77
    def described(retval=None, args={}):
 
78
        def decorator(func):
 
79
            if isinstance(args, dict):
 
80
                defs = func.func_defaults
 
81
                if defs is None:
 
82
                    defs = ()
 
83
                vars = func.func_code.co_varnames[:func.func_code.co_argcount]
 
84
                arg_pass = load_dict_args(vars, defs, args)
 
85
            else:
 
86
                assert isinstance(args, list)
 
87
                arg_pass = args
 
88
            func._method = (func.__name__, MethodDesc(arg_pass, retval))
 
89
            return func
 
90
        return decorator
 
91
    
 
92
    described = staticmethod(described)
 
93
 
 
94
described = BasicExternal.described
 
95
 
 
96
class Analyzer(object):
 
97
    def __init__(self, name, value, s_retval, s_args):
 
98
        self.name = name
 
99
        self.args, self.retval = value.args, value.retval
 
100
        self.s_retval = s_retval
 
101
        self.s_args = s_args
 
102
        self.value = value
 
103
    
 
104
    def __call__(self, *args):
 
105
        args = args[1:]
 
106
        assert len(self.s_args) == len(args),\
 
107
            "Function %s expects %d arguments, got %d instead" % (self.name,
 
108
                                              len(self.s_args), len(args))
 
109
        for num, (arg, expected) in enumerate(zip(args, self.s_args)):
 
110
            res = unionof(arg, expected)
 
111
            assert expected.contains(res)
 
112
        return self.s_retval
 
113
 
 
114
class ExternalType(ootype.OOType):
 
115
    class_dict = {}
 
116
    __name__ = "ExternalType"
 
117
 
 
118
    def __init__(self, _class):
 
119
        self._class_ = _class
 
120
        self._name = str(_class)
 
121
        self._superclass = None
 
122
        self._root = True
 
123
        self.updated = False
 
124
        self._data = frozendict(_class._fields), frozendict(_class._methods)
 
125
    
 
126
    def update_fields(self, _fields):
 
127
        for i, val in _fields.iteritems():
 
128
            self._fields[i] = annotation(val)
 
129
    
 
130
    def _is_compatible(type2):
 
131
        return type(type2) is ExternalType
 
132
    
 
133
    _is_compatible = staticmethod(_is_compatible)
 
134
    
 
135
    def update_methods(self, _methods):
 
136
        _signs = {}
 
137
        self._fields = {}
 
138
        for i, val in _methods.iteritems():
 
139
            retval = annotation(val.retval._type)
 
140
            values = [annotation(arg._type) for arg in val.args]
 
141
            s_args = [j for j in values]
 
142
            _signs[i] = MethodDesc(tuple(s_args), retval)
 
143
            next = annmodel.SomeBuiltin(Analyzer(i, val, retval, s_args), s_self = annmodel.SomeExternalBuiltin(self), methodname = i)
 
144
            next.const = True
 
145
            self._fields[i] = next
 
146
        self._methods = frozendict(_signs)
 
147
 
 
148
    def __hash__(self):
 
149
        return hash(self._name)
 
150
    
 
151
    def set_field(self, attr, knowntype):
 
152
        self.check_update()
 
153
        assert attr in self._fields
 
154
        field_ann = self._fields[attr]
 
155
        res = unionof(knowntype, field_ann)
 
156
        assert res.contains(knowntype)
 
157
    
 
158
    def check_update(self):
 
159
        if not self.updated:
 
160
            _fields, _methods = self._data
 
161
            self.update_methods(_methods)
 
162
            self.update_fields(_fields)
 
163
            self.updated = True
 
164
            self._fields = frozendict(self._fields)
 
165
            del self._data
 
166
    
 
167
    def get_field(self, attr):
 
168
        self.check_update()
 
169
        try:
 
170
            return self._fields[attr]
 
171
        except KeyError:
 
172
            from pypy.tool.error import NoSuchAttrError
 
173
            raise NoSuchAttrError("Basic external %s has no attribute %s" %
 
174
                                  (self._class_, attr))
 
175
 
 
176
    def find_method(self, meth):
 
177
        raise NotImplementedError()
 
178
    
 
179
    def __repr__(self):
 
180
        return "%s %s" % (self.__name__, self._name)
 
181
    
 
182
    def _defl(self):
 
183
        return _external_type(self, None)
 
184
 
 
185
class _external_type(object):
 
186
    
 
187
    def __init__(self, et, value):
 
188
        self._TYPE = et
 
189
        self.value = value
 
190
 
 
191
class Entry_basicexternalmeta(ExtRegistryEntry):
 
192
    _metatype_ = BasicMetaExternal
 
193
    
 
194
    def compute_annotation(self):
 
195
        return annmodel.SomeExternalBuiltin(self.bookkeeper.getexternaldesc\
 
196
            (self.type))
 
197
    
 
198
    def get_field_annotation(self, ext_obj, attr):
 
199
        return ext_obj.get_field(attr)
 
200
    
 
201
    #def get_arg_annotation(self, ext_obj, attr, s_pbc):
 
202
    #    s_field = ext_obj.get_field(attr)
 
203
    #    res = unionof(s_field, s_pbc)
 
204
    #    assert s_field.contains(res)
 
205
    #    return s_field.args_s
 
206
    
 
207
    def set_field_annotation(self, ext_obj, attr, s_val):
 
208
        ext_obj.set_field(attr, s_val)
 
209
 
 
210
class Entry_basicexternal(ExtRegistryEntry):
 
211
    _type_ = BasicExternal.__metaclass__
 
212
    
 
213
    def compute_result_annotation(self):
 
214
        if self.bookkeeper is None:
 
215
            return annmodel.SomeExternalBuiltin(ExternalType(self.instance))
 
216
        return annmodel.SomeExternalBuiltin(self.bookkeeper.getexternaldesc(self.instance))
 
217
    
 
218
    def specialize_call(self, hop):
 
219
        value = hop.r_result.lowleveltype
 
220
        return hop.genop('new', [Constant(value, concretetype=ootype.Void)], \
 
221
            resulttype = value)