[pypy-svn] r25695 - in pypy/dist/pypy: annotation rpython/rctypes rpython/rctypes/test
arigo at codespeak.net
arigo at codespeak.net
Tue Apr 11 12:39:52 CEST 2006
Author: arigo
Date: Tue Apr 11 12:39:50 2006
New Revision: 25695
Modified:
pypy/dist/pypy/annotation/binaryop.py
pypy/dist/pypy/annotation/model.py
pypy/dist/pypy/rpython/rctypes/rarray.py
pypy/dist/pypy/rpython/rctypes/rchar_p.py
pypy/dist/pypy/rpython/rctypes/rmodel.py
pypy/dist/pypy/rpython/rctypes/rpointer.py
pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
Log:
rctypes "progress":
* union for SomeCTypesObject
* prebuilt arrays
Blocker: the skipped test in test_rfunc.py. The problem is that
(c_char*10) is implemented as an array of structs containing each
a 'value' field of type char. This makes conversion to a regular
array of chars quite difficult. I am not sure that there is a
better solution than rewriting rctypes pointers to use addresses
systematically.
Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py (original)
+++ pypy/dist/pypy/annotation/binaryop.py Tue Apr 11 12:39:50 2006
@@ -724,10 +724,14 @@
return SomeAddress(is_null=False)
class __extend__(pairtype(SomeAddress, SomeImpossibleValue)):
+ # need to override this specifically to hide the 'raise UnionError'
+ # of pairtype(SomeAddress, SomeObject).
def union((s_addr, s_imp)):
return s_addr
class __extend__(pairtype(SomeImpossibleValue, SomeAddress)):
+ # need to override this specifically to hide the 'raise UnionError'
+ # of pairtype(SomeObject, SomeAddress).
def union((s_imp, s_addr)):
return s_addr
@@ -781,3 +785,19 @@
listdef = ListDef(None, SomeCTypesObject(s_cto.knowntype._type_))
return SomeList(listdef)
+class __extend__(pairtype(SomeCTypesObject, SomeCTypesObject)):
+ def union((s_cto1, s_cto2)):
+ if s_cto1.knowntype == s_cto2.knowntype:
+ states = {}
+ for s in [s_cto1, s_cto2]:
+ if s.memorystate != SomeCTypesObject.NOMEMORY:
+ states[s.memorystate] = True
+ if len(states) == 0:
+ state = SomeCTypesObject.NOMEMORY
+ elif len(states) == 1:
+ [state] = states.keys()
+ else:
+ state = SomeCTypesObject.MIXEDMEMORYOWNERSHIP
+ return SomeCTypesObject(s_cto1.knowntype, state)
+ else:
+ return SomeObject()
Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py (original)
+++ pypy/dist/pypy/annotation/model.py Tue Apr 11 12:39:50 2006
@@ -434,7 +434,7 @@
MEMORYALIAS = "MEMORYALIAS"
MIXEDMEMORYOWNERSHIP = "MIXEDMEMORYOWNERSHIP"
- def __init__(self, knowntype, memorystate=None):
+ def __init__(self, knowntype, memorystate):
if memorystate is None:
memorystate = knowntype.default_memorystate
self.knowntype = knowntype
Modified: pypy/dist/pypy/rpython/rctypes/rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rarray.py (original)
+++ pypy/dist/pypy/rpython/rctypes/rarray.py Tue Apr 11 12:39:50 2006
@@ -4,7 +4,7 @@
from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
from pypy.rpython.lltypesystem import lltype
from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rctypes.rmodel import CTypesRefRepr, reccopy
+from pypy.rpython.rctypes.rmodel import CTypesRefRepr, genreccopy, reccopy
ArrayType = type(ARRAY(c_int, 10))
@@ -25,6 +25,11 @@
super(ArrayRepr, self).__init__(rtyper, s_array, c_data_type)
+ def initialize_const(self, p, value):
+ for i in range(self.length):
+ llitem = self.r_item.convert_const(value[i])
+ reccopy(llitem.c_data, p.c_data[i])
+
def get_c_data_of_item(self, llops, v_array, v_index):
v_c_array = self.get_c_data(llops, v_array)
return llops.genop('getarraysubstruct', [v_c_array, v_index],
@@ -37,7 +42,7 @@
v_item_c_data = r_array.r_item.get_c_data(hop.llops, v_item)
v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
# copy the whole structure's content over
- reccopy(hop.llops, v_item_c_data, v_c_data)
+ genreccopy(hop.llops, v_item_c_data, v_c_data)
def rtype_getitem((r_array, r_int), hop):
v_array, v_index = hop.inputargs(r_array, lltype.Signed)
@@ -61,7 +66,12 @@
compute_annotation=arraytype_compute_annotation,
specialize_call=arraytype_specialize_call)
+def array_instance_compute_annotation(type, instance):
+ return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
+
def arraytype_get_repr(rtyper, s_array):
return ArrayRepr(rtyper, s_array)
-extregistry.register_metatype(ArrayType, get_repr=arraytype_get_repr)
+extregistry.register_metatype(ArrayType,
+ compute_annotation=array_instance_compute_annotation,
+ get_repr=arraytype_get_repr)
Modified: pypy/dist/pypy/rpython/rctypes/rchar_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rchar_p.py (original)
+++ pypy/dist/pypy/rpython/rctypes/rchar_p.py Tue Apr 11 12:39:50 2006
@@ -1,11 +1,13 @@
from pypy.rpython import extregistry
+from pypy.rpython.rmodel import inputconst
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.rstr import StringRepr, string_repr
from pypy.rpython.rctypes.rmodel import CTypesValueRepr
+from pypy.rpython.rctypes.rarray import ArrayRepr
from pypy.annotation import model as annmodel
from pypy.annotation.pairtype import pairtype
-from ctypes import c_char_p
+from ctypes import c_char, c_char_p
class CCharPRepr(CTypesValueRepr):
@@ -51,6 +53,25 @@
r_temp.setstring(llops, v_owned_box, v)
return llops.convertvar(v_owned_box, r_temp, r_to)
+##class __extend__(pairtype(ArrayRepr, CCharPRepr)):
+## def convert_from_to((r_from, r_to), v, llops):
+## if r_from.r_item.ctype != c_char:
+## return NotImplemented
+## # warning: no keepalives, only for short-lived conversions like
+## # in argument passing
+## r_temp = r_to.r_memoryowner
+## v_owned_box = r_temp.allocate_instance(llops)
+## v_char_array_ptr = r_from.get_c_data(llops, v)
+## v_char_array_adr = llops.genop('cast_ptr_to_adr', [v_char_array_ptr],
+## resulttype = llmemory.Address)
+## cofs = inputconst(lltype.Signed,
+## llmemory.itemoffsetof(r_from.ll_type) +
+## llmemory.offsetof(r_from.ll_type.OF, 'value'))
+## v_first_char_adr = llops.genop('adr_add', [v_char_array_adr, cofs],
+## resulttype = llmemory.Address)
+## r_temp.setvalue(llops, v_owned_box, v_first_char_adr)
+## return llops.convertvar(v_owned_box, r_temp, r_to)
+
CCHARP = llmemory.Address # char *
FIRSTITEMOFS = llmemory.ArrayItemsOffset(string_repr.lowleveltype.TO.chars)
Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rmodel.py (original)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py Tue Apr 11 12:39:50 2006
@@ -74,6 +74,32 @@
"Return extra keepalive fields used for the content of this object."
return []
+ def convert_const(self, value):
+ if isinstance(value, self.ctype):
+ key = "by_id", id(value)
+ keepalive = value
+ else:
+ if self.ownsmemory:
+ raise TyperError("convert_const(%r) but repr owns memory" % (
+ value,))
+ key = "by_value", value
+ keepalive = None
+ try:
+ return self.const_cache[key][0]
+ except KeyError:
+ p = lltype.malloc(self.r_memoryowner.lowleveltype.TO)
+ self.initialize_const(p, value)
+ if self.ownsmemory:
+ result = p
+ else:
+ # we must return a non-memory-owning box that keeps the
+ # memory-owning box alive
+ result = lltype.malloc(self.lowleveltype.TO)
+ result.c_data = p.c_data # initialize c_data pointer
+ result.c_data_owner_keepalive = p
+ self.const_cache[key] = result, keepalive
+ return result
+
def get_c_data(self, llops, v_box):
if self.ownsmemory:
inputargs = [v_box, inputconst(lltype.Void, "c_data")]
@@ -173,32 +199,6 @@
v_c_data = self.get_c_data(llops, v_box)
self.setvalue_inside_c_data(llops, v_c_data, v_value)
- def convert_const(self, value):
- if isinstance(value, self.ctype):
- key = "by_id", id(value)
- keepalive = value
- else:
- if self.ownsmemory:
- raise TyperError("convert_const(%r) but repr owns memory" % (
- value,))
- key = "by_value", value
- keepalive = None
- try:
- return self.const_cache[key][0]
- except KeyError:
- p = lltype.malloc(self.r_memoryowner.lowleveltype.TO)
- self.initialize_const(p, value)
- if self.ownsmemory:
- result = p
- else:
- # we must return a non-memory-owning box that keeps the
- # memory-owning box alive
- result = lltype.malloc(self.lowleveltype.TO)
- result.c_data = p.c_data # initialize c_data pointer
- result.c_data_owner_keepalive = p
- self.const_cache[key] = result, keepalive
- return result
-
def initialize_const(self, p, value):
if isinstance(value, self.ctype):
value = value.value
@@ -206,11 +206,35 @@
# ____________________________________________________________
-def reccopy(llops, v_source, v_dest):
- # helper to copy recursively a structure or array onto another.
+def reccopy(source, dest):
+ # copy recursively a structure or array onto another.
+ T = lltype.typeOf(source).TO
+ assert T == lltype.typeOf(dest).TO
+ assert isinstance(T, lltype.Struct) # XXX implement arrays
+ for name in T._names:
+ FIELDTYPE = getattr(T, name)
+ if isinstance(FIELDTYPE, lltype.ContainerType):
+ subsrc = getattr(source, name)
+ subdst = getattr(dest, name)
+ reccopy(subsrc, subdst)
+ else:
+ llvalue = getattr(source, name)
+ setattr(dest, name, llvalue)
+
+def reccopy_arrayitem(source, destarray, destindex):
+ ITEMTYPE = lltype.typeOf(destarray).TO.OF
+ if isinstance(ITEMTYPE, lltype.Primitive):
+ destarray[destindex] = source
+ else:
+ reccopy(source, destarray[destindex])
+
+def genreccopy(llops, v_source, v_dest):
+ # helper to generate the llops that copy recursively a structure
+ # or array onto another. 'v_source' and 'v_dest' can also be pairs
+ # (v, i) to mean the ith item of the array that v points to.
T = v_source.concretetype.TO
assert T == v_dest.concretetype.TO
- assert isinstance(T, lltype.Struct)
+ assert isinstance(T, lltype.Struct) # XXX implement arrays
for name in T._names:
FIELDTYPE = getattr(T, name)
cname = inputconst(lltype.Void, name)
@@ -218,7 +242,16 @@
RESTYPE = lltype.Ptr(FIELDTYPE)
v_subsrc = llops.genop('getsubstruct', [v_source, cname], RESTYPE)
v_subdst = llops.genop('getsubstruct', [v_dest, cname], RESTYPE)
- reccopy(llops, v_subsrc, v_subdst)
+ genreccopy(llops, v_subsrc, v_subdst)
else:
v_value = llops.genop('getfield', [v_source, cname], FIELDTYPE)
llops.genop('setfield', [v_dest, cname, v_value])
+
+def genreccopy_arrayitem(llops, v_source, v_destarray, v_destindex):
+ ITEMTYPE = v_destarray.concretetype.TO.OF
+ if isinstance(ITEMTYPE, lltype.Primitive):
+ llops.genop('setarrayitem', [v_destarray, v_destindex, v_source])
+ else:
+ v_dest = llops.genop('getarraysubstruct', [v_destarray, v_destindex],
+ resulttype = lltype.Ptr(ITEMTYPE))
+ genreccopy(llops, v_source, v_dest)
Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py (original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py Tue Apr 11 12:39:50 2006
@@ -4,7 +4,7 @@
from pypy.rpython.lltypesystem import lltype
from pypy.annotation import model as annmodel
from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rctypes.rmodel import CTypesValueRepr, reccopy
+from pypy.rpython.rctypes.rmodel import CTypesValueRepr, genreccopy
from ctypes import POINTER, pointer, c_int
@@ -86,7 +86,7 @@
# not supported by ctypes either
raise TyperError("assignment to pointer[x] with x != 0")
# copy the whole structure's content over
- reccopy(hop.llops, v_new_c_data, v_target)
+ genreccopy(hop.llops, v_new_c_data, v_target)
# ____________________________________________________________
Modified: pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rarray.py (original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rarray.py Tue Apr 11 12:39:50 2006
@@ -15,7 +15,7 @@
except ImportError:
py.test.skip("this test needs ctypes installed")
-from ctypes import c_int, ARRAY, POINTER, pointer
+from ctypes import c_int, c_short, ARRAY, POINTER, pointer
c_int_10 = ARRAY(c_int,10)
@@ -100,6 +100,23 @@
## py.test.raises(IndexError, "s = a.build_types(access_with_invalid_negative_index,[])")
+ def test_annotate_prebuilt(self):
+ my_array_2 = (c_short*10)(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
+ my_array_3 = (c_short*10)(0, 1, 8, 27, 64, 125, 216, 343, 512, 729)
+ def func(i, n):
+ if i == 2:
+ array = my_array_2
+ else:
+ array = my_array_3
+ return array[n]
+
+ t = TranslationContext()
+ a = t.buildannotator()
+ s = a.build_types(func, [int, int])
+ if conftest.option.view:
+ a.translator.view()
+ assert s.knowntype == int
+
class Test_specialization:
def test_specialize_array(self):
def create_array():
@@ -124,6 +141,21 @@
res = interpret(access_array, [44])
assert res == 1
+ def test_specialize_prebuilt(self):
+ my_array_2 = (c_short*10)(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
+ my_array_3 = (c_short*10)(0, 1, 8, 27, 64, 125, 216, 343, 512, 729)
+ def func(i, n):
+ if i == 2:
+ array = my_array_2
+ else:
+ array = my_array_3
+ return array[n]
+
+ res = interpret(func, [2, 6])
+ assert res == 36
+ res = interpret(func, [3, 7])
+ assert res == 343
+
class Test_compilation:
def test_compile_array_access(self):
def access_array():
Modified: pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py (original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py Tue Apr 11 12:39:50 2006
@@ -7,7 +7,7 @@
from pypy.rpython.rstr import string_repr
from pypy.rpython.lltypesystem import lltype, llmemory
-from ctypes import c_int, c_long, c_char_p
+from ctypes import c_int, c_long, c_char_p, c_char
labs = mylib.labs
@@ -36,6 +36,17 @@
assert labs(-42) == 42
return labs(n)
+def test_atoi():
+ assert atoi("") == 0
+ assert atoi("42z7") == 42
+ assert atoi("blah") == 0
+ assert atoi("18238") == 18238
+ A = c_char * 10
+ assert atoi(A('\x00')) == 0
+ assert atoi(A('4', '2', 'z', '7', '\x00')) == 42
+ assert atoi(A('b', 'l', 'a', 'h', '\x00')) == 0
+ assert atoi(A('1', '8', '2', '3', '8', '\x00')) == 18238
+
def test_ll_atoi():
keepalive = []
def str2addr(string):
@@ -78,6 +89,20 @@
res = [interpret(fn, [i]) for i in range(4)]
assert res == [0, 42, 0, 18238]
+ def test_specialize_atoi_char_array(self):
+ py.test.skip("in-progress")
+ A = c_char * 10
+ choices = [A('\x00'),
+ A('4', '2', 'z', '7', '\x00'),
+ A('b', 'l', 'a', 'h', '\x00'),
+ A('1', '8', '2', '3', '8', '\x00')]
+ def fn(n):
+ return atoi(choices[n])
+
+ assert fn(3) == 18238
+ res = [interpret(fn, [i]) for i in range(4)]
+ assert res == [0, 42, 0, 18238]
+
class Test_compile:
def test_compile_labs(self):
fn = compile(test_labs, [int])
More information about the Pypy-commit
mailing list