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

« back to all changes in this revision

Viewing changes to pypy/rlib/rctypes/rstruct.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.annotation import model as annmodel
 
2
from pypy.rlib.rctypes.implementation import CTypeController, getcontroller
 
3
from pypy.rlib.rctypes import rctypesobject
 
4
from pypy.rpython.extregistry import ExtRegistryEntry
 
5
from pypy.rpython.lltypesystem import lltype
 
6
from pypy.rlib.unroll import unrolling_iterable
 
7
 
 
8
from ctypes import Structure
 
9
 
 
10
StructType = type(Structure)
 
11
 
 
12
 
 
13
class StructCTypeController(CTypeController):
 
14
 
 
15
    def __init__(self, ctype):
 
16
        CTypeController.__init__(self, ctype)
 
17
 
 
18
        # Map the field names to their controllers
 
19
        controllers = []
 
20
        fields = []
 
21
        for name, field_ctype in ctype._fields_:
 
22
            controller = getcontroller(field_ctype)
 
23
            setattr(self, 'fieldcontroller_' + name, controller)
 
24
            controllers.append((name, controller))
 
25
            fields.append((name, controller.knowntype))
 
26
        external = getattr(ctype, '_external_', False)
 
27
        self.knowntype = rctypesobject.RStruct(ctype.__name__, fields,
 
28
                                               c_external = external)
 
29
        self.fieldcontrollers = controllers
 
30
 
 
31
        # Build a custom new() method where the setting of the fields
 
32
        # is unrolled
 
33
        unrolled_controllers = unrolling_iterable(controllers)
 
34
 
 
35
        def structnew(*args):
 
36
            obj = self.knowntype.allocate()
 
37
            if len(args) > len(fields):
 
38
                raise ValueError("too many arguments for this structure")
 
39
            for name, controller in unrolled_controllers:
 
40
                if args:
 
41
                    value = args[0]
 
42
                    args = args[1:]
 
43
                    if controller.is_box(value):
 
44
                        structsetboxattr(obj, name, value)
 
45
                    else:
 
46
                        structsetattr(obj, name, value)
 
47
            return obj
 
48
 
 
49
        self.new = structnew
 
50
 
 
51
        # Build custom getter and setter methods
 
52
        def structgetattr(obj, attr):
 
53
            controller = getattr(self, 'fieldcontroller_' + attr)
 
54
            itemobj = getattr(obj, 'ref_' + attr)()
 
55
            return controller.return_value(itemobj)
 
56
        structgetattr._annspecialcase_ = 'specialize:arg(1)'
 
57
 
 
58
        def structsetattr(obj, attr, value):
 
59
            controller = getattr(self, 'fieldcontroller_' + attr)
 
60
            itemobj = getattr(obj, 'ref_' + attr)()
 
61
            controller.store_value(itemobj, value)
 
62
        structsetattr._annspecialcase_ = 'specialize:arg(1)'
 
63
 
 
64
        def structsetboxattr(obj, attr, valuebox):
 
65
            controller = getattr(self, 'fieldcontroller_' + attr)
 
66
            itemobj = getattr(obj, 'ref_' + attr)()
 
67
            controller.store_box(itemobj, valuebox)
 
68
        structsetboxattr._annspecialcase_ = 'specialize:arg(1)'
 
69
 
 
70
        self.getattr = structgetattr
 
71
        self.setattr = structsetattr
 
72
        self.setboxattr = structsetboxattr
 
73
 
 
74
    def initialize_prebuilt(self, obj, x):
 
75
        for name, controller in self.fieldcontrollers:
 
76
            fieldbox = controller.convert(getattr(x, name))
 
77
            self.setboxattr(obj, name, fieldbox)
 
78
 
 
79
    def insert_constructor_keywords(self, lst, prefix, kwds):
 
80
        lst = list(lst)
 
81
        kwds = kwds.copy()
 
82
        for index, (name, field_ctype) in enumerate(self.ctype._fields_):
 
83
            if prefix+name in kwds:
 
84
                value = kwds.pop(prefix+name)
 
85
                while len(lst) <= index:
 
86
                    lst.append(None)
 
87
                if lst[index] is not None:
 
88
                    from pypy.rpython.error import TyperError
 
89
                    raise TyperError("duplicate value for argument %r" % name)
 
90
                lst[index] = value
 
91
        if kwds:
 
92
            from pypy.rpython.error import TyperError
 
93
            raise TyperError("unknown keyword(s): %r" % (kwds.keys(),))
 
94
        return lst
 
95
 
 
96
    def ctrl_new_ex(self, bookkeeper, *args_s, **kwds_s):
 
97
        if kwds_s:
 
98
            args_s = self.insert_constructor_keywords(args_s, 's_', kwds_s)
 
99
            for i in range(len(args_s)):
 
100
                if args_s[i] is None:
 
101
                    name, controller = self.fieldcontrollers[i]
 
102
                    x = controller.default_ctype_value()
 
103
                    args_s[i] = bookkeeper.immutablevalue(x)
 
104
        return CTypeController.ctrl_new(self, *args_s)
 
105
 
 
106
    def rtype_new(self, hop, **kwds_i):
 
107
        if kwds_i:
 
108
            lst = range(hop.nb_args)
 
109
            for key, index in kwds_i.items():
 
110
                lst[index] = None
 
111
            lst = self.insert_constructor_keywords(lst, 'i_', kwds_i)
 
112
            hop2 = hop.copy()
 
113
            hop2.nb_args = len(lst)
 
114
            hop2.args_v = []
 
115
            hop2.args_s = []
 
116
            hop2.args_r = []
 
117
            for i, index in enumerate(lst):
 
118
                if index is not None:
 
119
                    v = hop.args_v[index]
 
120
                    s = hop.args_s[index]
 
121
                    r = hop.args_r[index]
 
122
                else:
 
123
                    # must insert a default value
 
124
                    from pypy.objspace.flow.model import Constant
 
125
                    name, controller = self.fieldcontrollers[i]
 
126
                    x = controller.default_ctype_value()
 
127
                    v = Constant(x)
 
128
                    s = hop.rtyper.annotator.bookkeeper.immutablevalue(x)
 
129
                    r = hop.rtyper.getrepr(s)
 
130
                hop2.args_v.append(v)
 
131
                hop2.args_s.append(s)
 
132
                hop2.args_r.append(r)
 
133
            hop = hop2
 
134
        return CTypeController.rtype_new(self, hop)
 
135
 
 
136
 
 
137
StructCTypeController.register_for_metatype(StructType)
 
138
 
 
139
# ____________________________________________________________
 
140
 
 
141
def offsetof(Struct, fieldname):
 
142
    "Utility function that returns the offset of a field in a structure."
 
143
    return getattr(Struct, fieldname).offset
 
144
 
 
145
class OffsetOfFnEntry(ExtRegistryEntry):
 
146
    "Annotation and rtyping of calls to offsetof()"
 
147
    _about_ = offsetof
 
148
 
 
149
    def compute_result_annotation(self, s_Struct, s_fieldname):
 
150
        assert s_Struct.is_constant()
 
151
        assert s_fieldname.is_constant()
 
152
        ofs = offsetof(s_Struct.const, s_fieldname.const)
 
153
        assert ofs >= 0
 
154
        s_result = annmodel.SomeInteger(nonneg=True)
 
155
        s_result.const = ofs
 
156
        return s_result
 
157
 
 
158
    def specialize_call(self, hop):
 
159
        ofs = hop.s_result.const
 
160
        return hop.inputconst(lltype.Signed, ofs)