Commit a13fab25 authored by Haoyu Bai's avatar Haoyu Bai

improved the pure Python shadow module

parent f7d7598f
...@@ -2,13 +2,26 @@ ...@@ -2,13 +2,26 @@
compiled = False compiled = False
def empty_decorator(x): _Unspecified = object()
return x
# Function decorators # Function decorators
def _empty_decorator(x):
return x
def locals(**arg_types): def locals(**arg_types):
return empty_decorator return _empty_decorator
def test_assert_path_exists(path):
return _empty_decorator
class _EmptyDecoratorAndManager(object):
def __call__(self, x):
return x
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
pass
def inline(f, *args, **kwds): def inline(f, *args, **kwds):
if isinstance(f, basestring): if isinstance(f, basestring):
...@@ -38,11 +51,11 @@ def cmod(a, b): ...@@ -38,11 +51,11 @@ def cmod(a, b):
# Emulated language constructs # Emulated language constructs
def cast(type, arg): def cast(type, *args):
if hasattr(type, '__call__'): if hasattr(type, '__call__'):
return type(arg) return type(*args)
else: else:
return arg return args[0]
def sizeof(arg): def sizeof(arg):
return 1 return 1
...@@ -53,9 +66,9 @@ def typeof(arg): ...@@ -53,9 +66,9 @@ def typeof(arg):
def address(arg): def address(arg):
return pointer(type(arg))([arg]) return pointer(type(arg))([arg])
def declare(type=None, value=None, **kwds): def declare(type=None, value=_Unspecified, **kwds):
if type is not None and hasattr(type, '__call__'): if type is not None and hasattr(type, '__call__'):
if value: if value is not _Unspecified:
return type(value) return type(value)
else: else:
return type() return type()
...@@ -75,21 +88,24 @@ del _nogil ...@@ -75,21 +88,24 @@ del _nogil
# Emulated types # Emulated types
class CythonType(object): class CythonMetaType(type):
def __getitem__(type, ix):
return array(type, ix)
CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})
class CythonType(CythonTypeObject):
def _pointer(self, n=1): def _pointer(self, n=1):
for i in range(n): for i in range(n):
self = pointer(self) self = pointer(self)
return self return self
def __getitem__(self, ix):
return array(self, ix)
class PointerType(CythonType): class PointerType(CythonType):
def __init__(self, value=None): def __init__(self, value=None):
if isinstance(value, ArrayType): if isinstance(value, (ArrayType, PointerType)):
self._items = [cast(self._basetype, a) for a in value._items] self._items = [cast(self._basetype, a) for a in value._items]
elif isinstance(value, list): elif isinstance(value, list):
self._items = [cast(self._basetype, a) for a in value] self._items = [cast(self._basetype, a) for a in value]
...@@ -108,6 +124,14 @@ class PointerType(CythonType): ...@@ -108,6 +124,14 @@ class PointerType(CythonType):
raise IndexError("negative indexing not allowed in C") raise IndexError("negative indexing not allowed in C")
self._items[ix] = cast(self._basetype, value) self._items[ix] = cast(self._basetype, value)
def __eq__(self, value):
if value is None and not self._items:
return True
elif type(self) != type(value):
return False
else:
return self._items == value._items
class ArrayType(PointerType): class ArrayType(PointerType):
def __init__(self): def __init__(self):
...@@ -116,7 +140,16 @@ class ArrayType(PointerType): ...@@ -116,7 +140,16 @@ class ArrayType(PointerType):
class StructType(CythonType): class StructType(CythonType):
def __init__(self, **data): def __init__(self, cast_from=_Unspecified, **data):
if cast_from is not _Unspecified:
# do cast
if len(data) > 0:
raise ValueError('Cannot accept keyword arguments when casting.')
if type(cast_from) is not type(self):
raise ValueError('Cannot cast from %s'%cast_from)
for key, value in cast_from.__dict__.items():
setattr(self, key, value)
else:
for key, value in data.iteritems(): for key, value in data.iteritems():
setattr(self, key, value) setattr(self, key, value)
...@@ -129,10 +162,22 @@ class StructType(CythonType): ...@@ -129,10 +162,22 @@ class StructType(CythonType):
class UnionType(CythonType): class UnionType(CythonType):
def __init__(self, **data): def __init__(self, cast_from=_Unspecified, **data):
if cast_from is not _Unspecified:
# do type cast
if len(data) > 0: if len(data) > 0:
raise ValueError('Cannot accept keyword arguments when casting.')
if isinstance(cast_from, dict):
datadict = cast_from
elif type(cast_from) is type(self):
datadict = cast_from.__dict__
else:
raise ValueError('Cannot cast from %s'%cast_from)
else:
datadict = data
if len(datadict) > 1:
raise AttributeError("Union can only store one field at a time.") raise AttributeError("Union can only store one field at a time.")
for key, value in data.iteritems(): for key, value in datadict.iteritems():
setattr(self, key, value) setattr(self, key, value)
def __setattr__(self, key, value): def __setattr__(self, key, value):
...@@ -173,9 +218,8 @@ class typedef(CythonType): ...@@ -173,9 +218,8 @@ class typedef(CythonType):
def __init__(self, type): def __init__(self, type):
self._basetype = type self._basetype = type
def __call__(self, value=None): def __call__(self, *arg):
if value is not None: value = cast(self._basetype, *arg)
value = cast(self._basetype, value)
return value return value
...@@ -230,3 +274,4 @@ for t in int_types + float_types + complex_types + other_types: ...@@ -230,3 +274,4 @@ for t in int_types + float_types + complex_types + other_types:
void = typedef(None) void = typedef(None)
NULL = None NULL = None
...@@ -19,26 +19,24 @@ def test_sizeof(): ...@@ -19,26 +19,24 @@ def test_sizeof():
else: else:
print(cython.sizeof(cython.char) == 1) print(cython.sizeof(cython.char) == 1)
## CURRENTLY BROKEN - FIXME!! def test_declare(n):
"""
## def test_declare(n): >>> test_declare(100)
## """ (100, 100)
## >>> test_declare(100) >>> test_declare(100.5)
## (100, 100) (100, 100)
## >>> test_declare(100.5) >>> test_declare(None) #doctest: +ELLIPSIS
## (100, 100) Traceback (most recent call last):
## >>> test_declare(None) ...
## Traceback (most recent call last): TypeError: ...
## ... """
## TypeError: an integer is required x = cython.declare(cython.int)
## """ y = cython.declare(cython.int, n)
## x = cython.declare(cython.int) if cython.compiled:
## y = cython.declare(cython.int, n) cython.declare(xx=cython.int, yy=cython.long)
## if cython.compiled: i = sizeof(xx)
## cython.declare(xx=cython.int, yy=cython.long) ptr = cython.declare(cython.p_int, cython.address(y))
## i = sizeof(xx) return y, ptr[0]
## ptr = cython.declare(cython.p_int, cython.address(y))
## return y, ptr[0]
@cython.locals(x=cython.double, n=cython.int) @cython.locals(x=cython.double, n=cython.int)
def test_cast(x): def test_cast(x):
...@@ -59,6 +57,7 @@ def test_address(x): ...@@ -59,6 +57,7 @@ def test_address(x):
return y[0] return y[0]
## CURRENTLY BROKEN - FIXME!! ## CURRENTLY BROKEN - FIXME!!
## Is this test make sense? Implicit conversion in pure Python??
## @cython.locals(x=cython.int) ## @cython.locals(x=cython.int)
## @cython.locals(y=cython.bint) ## @cython.locals(y=cython.bint)
...@@ -93,21 +92,19 @@ def test_with_nogil(nogil): ...@@ -93,21 +92,19 @@ def test_with_nogil(nogil):
result = True result = True
return result return result
## CURRENTLY BROKEN - FIXME!! MyUnion = cython.union(n=cython.int, x=cython.double)
MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
MyStruct2 = cython.typedef(MyStruct[2])
## MyUnion = cython.union(n=cython.int, x=cython.double) def test_struct(n, x):
## MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion) """
## MyStruct2 = cython.typedef(MyStruct[2]) >>> test_struct(389, 1.64493)
(389, 1.64493)
## def test_struct(n, x): """
## """ a = cython.declare(MyStruct2)
## >>> test_struct(389, 1.64493) a[0] = MyStruct(is_integral=True, data=MyUnion(n=n))
## (389, 1.64493) a[1] = MyStruct(is_integral=False, data={'x': x})
## """ return a[0].data.n, a[1].data.x
## a = cython.declare(MyStruct2)
## a[0] = MyStruct(True, data=MyUnion(n=n))
## a[1] = MyStruct(is_integral=False, data={'x': x})
## return a[0].data.n, a[1].data.x
import cython as cy import cython as cy
from cython import declare, cast, locals, address, typedef, p_void, compiled from cython import declare, cast, locals, address, typedef, p_void, compiled
...@@ -116,24 +113,21 @@ from cython import declare as my_declare, locals as my_locals, p_void as my_void ...@@ -116,24 +113,21 @@ from cython import declare as my_declare, locals as my_locals, p_void as my_void
@my_locals(a=cython.p_void) @my_locals(a=cython.p_void)
def test_imports(): def test_imports():
""" """
>>> test_imports() # (True, True) >>> test_imports()
True (True, True)
""" """
a = cython.NULL a = cython.NULL
b = declare(p_void, cython.NULL) b = declare(p_void, cython.NULL)
c = my_declare(my_void_star, cython.NULL) c = my_declare(my_void_star, cython.NULL)
d = cy.declare(cy.p_void, cython.NULL) d = cy.declare(cy.p_void, cython.NULL)
## CURRENTLY BROKEN - FIXME!! return a == d, compiled == my_compiled
#return a == d, compiled == my_compiled
return compiled == my_compiled
## CURRENTLY BROKEN - FIXME!! ## CURRENTLY BROKEN - FIXME!!
## MyStruct3 = typedef(MyStruct[3]) # MyStruct3 = typedef(MyStruct[3])
## MyStruct4 = my_typedef(MyStruct[4]) # MyStruct4 = my_typedef(MyStruct[4])
## MyStruct5 = cy.typedef(MyStruct[5]) # MyStruct5 = cy.typedef(MyStruct[5])
def test_declare_c_types(n): def test_declare_c_types(n):
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment