2
""" External objects registry,
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
16
class CallableEntry(ExtRegistryEntry):
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)
25
class BasicMetaExternal(type):
26
def _is_compatible(type2):
27
return type(type2) is BasicMetaExternal
29
def __new__(self, _name, _type, _vars):
30
retval = type.__new__(self, _name, _type, _vars)
31
if not 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
39
_is_compatible = staticmethod(_is_compatible)
42
""" Small wrapper, which tries to resemble example -> python type
43
which can go to annotation path
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])
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")
57
for arg in xrange(1, argcount - len(defs)):
58
assert varnames[arg] in args, "Don't have type for arg %s" % varnames[arg]
61
start_pos = argcount - len(defs)
62
for arg in xrange(1, argcount):
63
varname = varnames[arg]
65
arg_pass.append((varname, args[varname]))
67
arg_pass.append((varname, typeof(defs[arg - start_pos])))
70
class BasicExternal(object):
71
__metaclass__ = BasicMetaExternal
77
def described(retval=None, args={}):
79
if isinstance(args, dict):
80
defs = func.func_defaults
83
vars = func.func_code.co_varnames[:func.func_code.co_argcount]
84
arg_pass = load_dict_args(vars, defs, args)
86
assert isinstance(args, list)
88
func._method = (func.__name__, MethodDesc(arg_pass, retval))
92
described = staticmethod(described)
94
described = BasicExternal.described
96
class Analyzer(object):
97
def __init__(self, name, value, s_retval, s_args):
99
self.args, self.retval = value.args, value.retval
100
self.s_retval = s_retval
104
def __call__(self, *args):
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)
114
class ExternalType(ootype.OOType):
116
__name__ = "ExternalType"
118
def __init__(self, _class):
119
self._class_ = _class
120
self._name = str(_class)
121
self._superclass = None
124
self._data = frozendict(_class._fields), frozendict(_class._methods)
126
def update_fields(self, _fields):
127
for i, val in _fields.iteritems():
128
self._fields[i] = annotation(val)
130
def _is_compatible(type2):
131
return type(type2) is ExternalType
133
_is_compatible = staticmethod(_is_compatible)
135
def update_methods(self, _methods):
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)
145
self._fields[i] = next
146
self._methods = frozendict(_signs)
149
return hash(self._name)
151
def set_field(self, attr, knowntype):
153
assert attr in self._fields
154
field_ann = self._fields[attr]
155
res = unionof(knowntype, field_ann)
156
assert res.contains(knowntype)
158
def check_update(self):
160
_fields, _methods = self._data
161
self.update_methods(_methods)
162
self.update_fields(_fields)
164
self._fields = frozendict(self._fields)
167
def get_field(self, attr):
170
return self._fields[attr]
172
from pypy.tool.error import NoSuchAttrError
173
raise NoSuchAttrError("Basic external %s has no attribute %s" %
174
(self._class_, attr))
176
def find_method(self, meth):
177
raise NotImplementedError()
180
return "%s %s" % (self.__name__, self._name)
183
return _external_type(self, None)
185
class _external_type(object):
187
def __init__(self, et, value):
191
class Entry_basicexternalmeta(ExtRegistryEntry):
192
_metatype_ = BasicMetaExternal
194
def compute_annotation(self):
195
return annmodel.SomeExternalBuiltin(self.bookkeeper.getexternaldesc\
198
def get_field_annotation(self, ext_obj, attr):
199
return ext_obj.get_field(attr)
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
207
def set_field_annotation(self, ext_obj, attr, s_val):
208
ext_obj.set_field(attr, s_val)
210
class Entry_basicexternal(ExtRegistryEntry):
211
_type_ = BasicExternal.__metaclass__
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))
218
def specialize_call(self, hop):
219
value = hop.r_result.lowleveltype
220
return hop.genop('new', [Constant(value, concretetype=ootype.Void)], \