1
from ctypes import ARRAY, c_int
2
from pypy.rpython.error import TyperError
3
from pypy.rpython.lltypesystem.rstr import string_repr, emptystr
4
from pypy.rpython.rmodel import IntegerRepr, inputconst
5
from pypy.rpython.rslice import AbstractSliceRepr
6
from pypy.rpython.lltypesystem import lltype
7
from pypy.annotation.pairtype import pairtype
8
from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr
9
from pypy.rpython.rctypes.rmodel import genreccopy_arrayitem, reccopy, C_ZERO
10
from pypy.rpython.rctypes.rprimitive import PrimitiveRepr
11
from pypy.rpython.rctypes.rpointer import PointerRepr
12
from pypy.rpython.rctypes.aarray import VarSizedArrayType
13
from pypy.annotation.model import SomeCTypesObject
14
from pypy.objspace.flow.model import Constant
16
ArrayType = type(ARRAY(c_int, 10))
19
class ArrayRepr(CTypesRefRepr):
20
def __init__(self, rtyper, s_array):
21
array_ctype = s_array.knowntype
23
item_ctype = array_ctype._type_
24
if isinstance(array_ctype, VarSizedArrayType):
27
self.length = array_ctype._length_
29
# Find the repr and low-level type of items from their ctype
30
self.r_item = rtyper.getrepr(SomeCTypesObject(item_ctype,
33
# Here, self.c_data_type == self.ll_type
34
if self.length is not None:
35
c_data_type = lltype.FixedSizeArray(self.r_item.ll_type,
38
c_data_type = lltype.Array(self.r_item.ll_type,
39
hints={'nolength': True})
41
super(ArrayRepr, self).__init__(rtyper, s_array, c_data_type)
43
def get_content_keepalive_type(self):
44
"An extra array of keepalives, one per item."
45
item_keepalive_type = self.r_item.get_content_keepalive_type()
46
if not item_keepalive_type:
48
elif self.length is not None:
49
return lltype.FixedSizeArray(item_keepalive_type, self.length)
51
raise NotImplementedError("XXX not supported yet: "
52
"var-sized arrays of pointers")
54
def initialize_const(self, p, value):
55
for i in range(self.length):
56
llitem = self.r_item.convert_const(value[i])
57
if isinstance(self.r_item, CTypesRefRepr):
59
reccopy(llitem.c_data, p.c_data[i])
62
p.c_data[i] = llitem.c_data[0]
64
def rtype_getattr(self, hop):
65
s_attr = hop.args_s[1]
66
assert s_attr.is_constant()
67
assert s_attr.const == 'value'
68
assert self.r_item.ll_type == lltype.Char # .value: char arrays only
69
hop.exception_cannot_occur()
71
return hop.inputconst(lltype.typeOf(emptystr), emptystr)
73
v_box = hop.inputarg(self, 0)
74
return hop.gendirectcall(ll_chararrayvalue, v_box)
76
def get_c_data_of_item(self, llops, v_array, v_index):
77
v_c_array = self.get_c_data(llops, v_array)
78
if isinstance(self.r_item, CTypesRefRepr):
80
return llops.genop('getarraysubstruct', [v_c_array, v_index],
81
lltype.Ptr(self.r_item.c_data_type))
84
P = lltype.Ptr(lltype.FixedSizeArray(self.r_item.ll_type, 1))
85
v_items = llops.genop('direct_arrayitems', [v_c_array],
87
if isinstance(v_index, Constant) and v_index.value == 0:
88
pass # skip direct_ptradd
90
v_items = llops.genop('direct_ptradd', [v_items, v_index],
94
def get_item_value(self, llops, v_array, v_index):
96
assert isinstance(self.r_item, CTypesValueRepr)
97
v_c_array = self.get_c_data(llops, v_array)
98
return llops.genop('getarrayitem', [v_c_array, v_index],
99
resulttype = self.r_item.ll_type)
101
## def set_item_value(self, llops, v_array, v_index, v_newvalue):
102
## # ByValue case only
103
## assert isinstance(self.r_item, CTypesValueRepr)
104
## v_c_array = self.get_c_data(llops, v_array)
105
## llops.genop('setarrayitem', [v_c_array, v_index, v_newvalue])
107
def setitem(self, llops, v_array, v_index, v_item):
108
v_newvalue = self.r_item.get_c_data_or_value(llops, v_item)
109
# copy the new value (which might be a whole structure)
110
v_c_array = self.get_c_data(llops, v_array)
111
genreccopy_arrayitem(llops, v_newvalue, v_c_array, v_index)
112
# copy the keepalive information too
113
v_keepalive_array = self.getkeepalive(llops, v_array)
114
if v_keepalive_array is not None:
115
v_newkeepalive = self.r_item.getkeepalive(llops, v_item)
116
genreccopy_arrayitem(llops, v_newkeepalive,
117
v_keepalive_array, v_index)
119
def initializeitems(self, llops, v_array, items_v):
120
for i, v_item in enumerate(items_v):
121
c_index = inputconst(lltype.Signed, i)
122
self.setitem(llops, v_array, c_index, v_item)
125
class __extend__(pairtype(ArrayRepr, IntegerRepr)):
126
def rtype_getitem((r_array, r_int), hop):
127
v_array, v_index = hop.inputargs(r_array, lltype.Signed)
128
hop.exception_cannot_occur()
129
if isinstance(r_array.r_item, PrimitiveRepr):
130
# primitive case (optimization; the below also works in this case)
131
# NB. this optimization is invalid for PointerReprs! See for
132
# example: a[0].contents = ... to change the first pointer of
133
# an array of pointers.
134
v_value = r_array.get_item_value(hop.llops, v_array, v_index)
135
return r_array.r_item.return_value(hop.llops, v_value)
138
v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
139
return r_array.r_item.return_c_data(hop.llops, v_c_data)
141
def rtype_setitem((r_array, r_int), hop):
142
v_array, v_index, v_item = hop.inputargs(r_array, lltype.Signed,
144
hop.exception_cannot_occur()
145
r_array.setitem(hop.llops, v_array, v_index, v_item)
148
class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)):
149
def rtype_getitem((r_array, r_slic), hop):
150
rs = hop.rtyper.type_system.rslice
151
hop.exception_cannot_occur()
152
if r_slic == rs.startstop_slice_repr:
153
# slicing: char array only
154
assert r_array.r_item.ll_type == lltype.Char
155
if r_array.length == 0:
156
return hop.inputconst(lltype.typeOf(emptystr), emptystr)
157
v_array, v_slice = hop.inputargs(r_array, rs.startstop_slice_repr)
158
return hop.gendirectcall(ll_chararrayslice, v_array, v_slice)
159
raise TyperError('getitem does not support slices with %r' % (r_slic,))
162
class __extend__(pairtype(ArrayRepr, PointerRepr)):
163
def convert_from_to((r_from, r_to), v, llops):
165
r_temp = r_to.r_memoryowner
166
v_owned_box = r_temp.allocate_instance(llops)
167
v_c_array = r_from.get_c_data_of_item(llops, v, C_ZERO)
168
r_temp.setvalue(llops, v_owned_box, v_c_array)
169
return llops.convertvar(v_owned_box, r_temp, r_to)
172
def ll_chararrayvalue(box):
173
from pypy.rpython.rctypes import rchar_p
175
length = rchar_p.ll_strnlen(lltype.direct_arrayitems(p), len(p))
176
newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
178
for i in range(length):
179
newstr.chars[i] = p[i]
182
def ll_chararrayslice(box, slice):
183
from pypy.rpython.rctypes import rchar_p
187
length = stop - start
189
newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
191
for i in range(length):
192
newstr.chars[i] = p[start+i]