work-around for ticket #691: look up unknown global names in builtins at runtime
[cython.git] / Cython / Shadow.py
1 # cython.* namespace for pure mode.
2
3 compiled = False
4
5 _Unspecified = object()
6
7 # Function decorators
8
9 def _empty_decorator(x):
10     return x
11
12 def locals(**arg_types):
13     return _empty_decorator
14
15 def test_assert_path_exists(path):
16     return _empty_decorator
17
18 def test_fail_if_path_exists(path):
19     return _empty_decorator
20
21 class _EmptyDecoratorAndManager(object):
22     def __call__(self, x):
23         return x
24     def __enter__(self):
25         pass
26     def __exit__(self, exc_type, exc_value, traceback):
27         pass
28
29 def inline(f, *args, **kwds):
30   if isinstance(f, basestring):
31     from Cython.Build.Inline import cython_inline
32     return cython_inline(f, *args, **kwds)
33   else:
34     assert len(args) == len(kwds) == 0
35     return f
36
37 def compile(f):
38     from Cython.Build.Inline import RuntimeCompiledFunction
39     return RuntimeCompiledFunction(f)
40
41 # Special functions
42
43 def cdiv(a, b):
44     q = a / b
45     if q < 0:
46         q += 1
47
48 def cmod(a, b):
49     r = a % b
50     if (a*b) < 0:
51         r -= b
52     return r
53
54
55 # Emulated language constructs
56
57 def cast(type, *args):
58     if hasattr(type, '__call__'):
59         return type(*args)
60     else:
61         return args[0]
62
63 def sizeof(arg):
64     return 1
65
66 def typeof(arg):
67     return type(arg)
68
69 def address(arg):
70     return pointer(type(arg))([arg])
71
72 def declare(type=None, value=_Unspecified, **kwds):
73     if type is not None and hasattr(type, '__call__'):
74         if value is not _Unspecified:
75             return type(value)
76         else:
77             return type()
78     else:
79         return value
80
81 class _nogil(object):
82     """Support for 'with nogil' statement
83     """
84     def __enter__(self):
85         pass
86     def __exit__(self, exc_class, exc, tb):
87         return exc_class is None
88
89 nogil = _nogil()
90 del _nogil
91
92 # Emulated types
93
94 class CythonMetaType(type):
95
96     def __getitem__(type, ix):
97         return array(type, ix)
98
99 CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})
100
101 class CythonType(CythonTypeObject):
102
103     def _pointer(self, n=1):
104         for i in range(n):
105             self = pointer(self)
106         return self
107
108 class PointerType(CythonType):
109
110     def __init__(self, value=None):
111         if isinstance(value, (ArrayType, PointerType)):
112             self._items = [cast(self._basetype, a) for a in value._items]
113         elif isinstance(value, list):
114             self._items = [cast(self._basetype, a) for a in value]
115         elif value is None or value is 0:
116             self._items = []
117         else:
118             raise ValueError
119
120     def __getitem__(self, ix):
121         if ix < 0:
122             raise IndexError("negative indexing not allowed in C")
123         return self._items[ix]
124
125     def __setitem__(self, ix, value):
126         if ix < 0:
127             raise IndexError("negative indexing not allowed in C")
128         self._items[ix] = cast(self._basetype, value)
129
130     def __eq__(self, value):
131         if value is None and not self._items:
132             return True
133         elif type(self) != type(value):
134             return False
135         else:
136             return not self._items and not value._items
137
138 class ArrayType(PointerType):
139
140     def __init__(self):
141         self._items = [None] * self._n
142
143
144 class StructType(CythonType):
145
146     def __init__(self, cast_from=_Unspecified, **data):
147         if cast_from is not _Unspecified:
148             # do cast
149             if len(data) > 0:
150                 raise ValueError('Cannot accept keyword arguments when casting.')
151             if type(cast_from) is not type(self):
152                 raise ValueError('Cannot cast from %s'%cast_from)
153             for key, value in cast_from.__dict__.items():
154                 setattr(self, key, value)
155         else:
156             for key, value in data.iteritems():
157                 setattr(self, key, value)
158
159     def __setattr__(self, key, value):
160         if key in self._members:
161             self.__dict__[key] = cast(self._members[key], value)
162         else:
163             raise AttributeError("Struct has no member '%s'" % key)
164
165
166 class UnionType(CythonType):
167
168     def __init__(self, cast_from=_Unspecified, **data):
169         if cast_from is not _Unspecified:
170             # do type cast
171             if len(data) > 0:
172                 raise ValueError('Cannot accept keyword arguments when casting.')
173             if isinstance(cast_from, dict):
174                 datadict = cast_from
175             elif type(cast_from) is type(self):
176                 datadict = cast_from.__dict__
177             else:
178                 raise ValueError('Cannot cast from %s'%cast_from)
179         else:
180             datadict = data
181         if len(datadict) > 1:
182             raise AttributeError("Union can only store one field at a time.")
183         for key, value in datadict.iteritems():
184             setattr(self, key, value)
185
186     def __setattr__(self, key, value):
187         if key in '__dict__':
188             CythonType.__setattr__(self, key, value)
189         elif key in self._members:
190             self.__dict__ = {key: cast(self._members[key], value)}
191         else:
192             raise AttributeError("Union has no member '%s'" % key)
193
194 def pointer(basetype):
195     class PointerInstance(PointerType):
196         _basetype = basetype
197     return PointerInstance
198
199 def array(basetype, n):
200     class ArrayInstance(ArrayType):
201         _basetype = basetype
202         _n = n
203     return ArrayInstance
204
205 def struct(**members):
206     class StructInstance(StructType):
207         _members = members
208     for key in members:
209         setattr(StructInstance, key, None)
210     return StructInstance
211
212 def union(**members):
213     class UnionInstance(UnionType):
214         _members = members
215     for key in members:
216         setattr(UnionInstance, key, None)
217     return UnionInstance
218
219 class typedef(CythonType):
220
221     def __init__(self, type):
222         self._basetype = type
223
224     def __call__(self, *arg):
225         value = cast(self._basetype, *arg)
226         return value
227
228
229
230 py_int = int
231 try:
232     py_long = long
233 except NameError: # Py3
234     py_long = int
235 py_float = float
236 py_complex = complex
237
238
239 try:
240     # Python 3
241     from builtins import set, frozenset
242 except ImportError:
243     try:
244         # Python 2.4+
245         from __builtin__ import set, frozenset
246     except ImportError:
247         # Py 2.3
248         from sets import Set as set, ImmutableSet as frozenset
249
250 # Predefined types
251
252 int_types = ['char', 'short', 'Py_UNICODE', 'int', 'long', 'longlong', 'Py_ssize_t', 'size_t']
253 float_types = ['longdouble', 'double', 'float']
254 complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
255 other_types = ['bint', 'void']
256
257 gs = globals()
258
259 for name in int_types:
260     gs[name] = typedef(py_int)
261     if name != 'Py_UNICODE' and not name.endswith('size_t'):
262         gs['u'+name] = typedef(py_int)
263         gs['s'+name] = typedef(py_int)
264
265 for name in float_types:
266     gs[name] = typedef(py_float)
267
268 for name in complex_types:
269     gs[name] = typedef(py_complex)
270
271 bint = typedef(bool)
272 void = typedef(int)
273
274 for t in int_types + float_types + complex_types + other_types:
275     for i in range(1, 4):
276         gs["%s_%s" % ('p'*i, t)] = globals()[t]._pointer(i)
277
278 void = typedef(None)
279 NULL = p_void(0)