Cython 3.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. Cython/Build/BuildExecutable.py +169 -0
  2. Cython/Build/Cache.py +199 -0
  3. Cython/Build/Cythonize.py +323 -0
  4. Cython/Build/Dependencies.py +1306 -0
  5. Cython/Build/Distutils.py +1 -0
  6. Cython/Build/Inline.py +463 -0
  7. Cython/Build/IpythonMagic.py +560 -0
  8. Cython/Build/SharedModule.py +76 -0
  9. Cython/Build/Tests/TestCyCache.py +194 -0
  10. Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
  11. Cython/Build/Tests/TestDependencies.py +133 -0
  12. Cython/Build/Tests/TestInline.py +177 -0
  13. Cython/Build/Tests/TestIpythonMagic.py +287 -0
  14. Cython/Build/Tests/TestRecythonize.py +212 -0
  15. Cython/Build/Tests/TestStripLiterals.py +155 -0
  16. Cython/Build/Tests/__init__.py +1 -0
  17. Cython/Build/__init__.py +8 -0
  18. Cython/CodeWriter.py +811 -0
  19. Cython/Compiler/AnalysedTreeTransforms.py +97 -0
  20. Cython/Compiler/Annotate.py +326 -0
  21. Cython/Compiler/AutoDocTransforms.py +320 -0
  22. Cython/Compiler/Buffer.py +680 -0
  23. Cython/Compiler/Builtin.py +934 -0
  24. Cython/Compiler/CmdLine.py +259 -0
  25. Cython/Compiler/Code.pxd +148 -0
  26. Cython/Compiler/Code.py +3375 -0
  27. Cython/Compiler/CodeGeneration.py +33 -0
  28. Cython/Compiler/CythonScope.py +187 -0
  29. Cython/Compiler/Dataclass.py +868 -0
  30. Cython/Compiler/DebugFlags.py +24 -0
  31. Cython/Compiler/Errors.py +295 -0
  32. Cython/Compiler/ExprNodes.py +15267 -0
  33. Cython/Compiler/FlowControl.pxd +97 -0
  34. Cython/Compiler/FlowControl.py +1455 -0
  35. Cython/Compiler/FusedNode.py +1002 -0
  36. Cython/Compiler/Future.py +16 -0
  37. Cython/Compiler/Interpreter.py +57 -0
  38. Cython/Compiler/Lexicon.py +340 -0
  39. Cython/Compiler/LineTable.py +114 -0
  40. Cython/Compiler/Main.py +853 -0
  41. Cython/Compiler/MatchCaseNodes.py +259 -0
  42. Cython/Compiler/MemoryView.py +922 -0
  43. Cython/Compiler/ModuleNode.py +4024 -0
  44. Cython/Compiler/Naming.py +374 -0
  45. Cython/Compiler/Nodes.py +10826 -0
  46. Cython/Compiler/Optimize.py +5256 -0
  47. Cython/Compiler/Options.py +835 -0
  48. Cython/Compiler/ParseTreeTransforms.pxd +77 -0
  49. Cython/Compiler/ParseTreeTransforms.py +4509 -0
  50. Cython/Compiler/Parsing.pxd +9 -0
  51. Cython/Compiler/Parsing.py +4789 -0
  52. Cython/Compiler/Pipeline.py +439 -0
  53. Cython/Compiler/PyrexTypes.py +5762 -0
  54. Cython/Compiler/Pythran.py +232 -0
  55. Cython/Compiler/Scanning.pxd +40 -0
  56. Cython/Compiler/Scanning.py +577 -0
  57. Cython/Compiler/StringEncoding.py +347 -0
  58. Cython/Compiler/Symtab.py +3080 -0
  59. Cython/Compiler/Tests/TestBuffer.py +105 -0
  60. Cython/Compiler/Tests/TestBuiltin.py +72 -0
  61. Cython/Compiler/Tests/TestCmdLine.py +586 -0
  62. Cython/Compiler/Tests/TestCode.py +86 -0
  63. Cython/Compiler/Tests/TestFlowControl.py +65 -0
  64. Cython/Compiler/Tests/TestGrammar.py +202 -0
  65. Cython/Compiler/Tests/TestMemView.py +71 -0
  66. Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
  67. Cython/Compiler/Tests/TestScanning.py +134 -0
  68. Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
  69. Cython/Compiler/Tests/TestStringEncoding.py +33 -0
  70. Cython/Compiler/Tests/TestTreeFragment.py +63 -0
  71. Cython/Compiler/Tests/TestTreePath.py +103 -0
  72. Cython/Compiler/Tests/TestTypes.py +75 -0
  73. Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
  74. Cython/Compiler/Tests/TestVisitor.py +61 -0
  75. Cython/Compiler/Tests/Utils.py +36 -0
  76. Cython/Compiler/Tests/__init__.py +1 -0
  77. Cython/Compiler/TreeFragment.py +278 -0
  78. Cython/Compiler/TreePath.py +303 -0
  79. Cython/Compiler/TypeInference.py +584 -0
  80. Cython/Compiler/TypeSlots.py +1181 -0
  81. Cython/Compiler/UFuncs.py +311 -0
  82. Cython/Compiler/UtilNodes.py +389 -0
  83. Cython/Compiler/UtilityCode.py +344 -0
  84. Cython/Compiler/Version.py +8 -0
  85. Cython/Compiler/Visitor.pxd +53 -0
  86. Cython/Compiler/Visitor.py +861 -0
  87. Cython/Compiler/__init__.py +1 -0
  88. Cython/Coverage.py +448 -0
  89. Cython/Debugger/Cygdb.py +175 -0
  90. Cython/Debugger/DebugWriter.py +82 -0
  91. Cython/Debugger/Tests/TestLibCython.py +275 -0
  92. Cython/Debugger/Tests/__init__.py +1 -0
  93. Cython/Debugger/Tests/cfuncs.c +8 -0
  94. Cython/Debugger/Tests/codefile +49 -0
  95. Cython/Debugger/Tests/test_libcython_in_gdb.py +578 -0
  96. Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
  97. Cython/Debugger/__init__.py +1 -0
  98. Cython/Debugger/libcython.py +1548 -0
  99. Cython/Debugger/libpython.py +2821 -0
  100. Cython/Debugging.py +20 -0
  101. Cython/Distutils/__init__.py +2 -0
  102. Cython/Distutils/build_ext.py +139 -0
  103. Cython/Distutils/extension.py +96 -0
  104. Cython/Distutils/old_build_ext.py +351 -0
  105. Cython/Includes/cpython/__init__.pxd +173 -0
  106. Cython/Includes/cpython/array.pxd +174 -0
  107. Cython/Includes/cpython/bool.pxd +37 -0
  108. Cython/Includes/cpython/buffer.pxd +112 -0
  109. Cython/Includes/cpython/bytearray.pxd +33 -0
  110. Cython/Includes/cpython/bytes.pxd +200 -0
  111. Cython/Includes/cpython/cellobject.pxd +35 -0
  112. Cython/Includes/cpython/ceval.pxd +8 -0
  113. Cython/Includes/cpython/codecs.pxd +121 -0
  114. Cython/Includes/cpython/complex.pxd +60 -0
  115. Cython/Includes/cpython/contextvars.pxd +145 -0
  116. Cython/Includes/cpython/conversion.pxd +36 -0
  117. Cython/Includes/cpython/datetime.pxd +395 -0
  118. Cython/Includes/cpython/descr.pxd +26 -0
  119. Cython/Includes/cpython/dict.pxd +187 -0
  120. Cython/Includes/cpython/exc.pxd +263 -0
  121. Cython/Includes/cpython/fileobject.pxd +57 -0
  122. Cython/Includes/cpython/float.pxd +47 -0
  123. Cython/Includes/cpython/function.pxd +65 -0
  124. Cython/Includes/cpython/genobject.pxd +25 -0
  125. Cython/Includes/cpython/getargs.pxd +12 -0
  126. Cython/Includes/cpython/instance.pxd +25 -0
  127. Cython/Includes/cpython/iterator.pxd +36 -0
  128. Cython/Includes/cpython/iterobject.pxd +24 -0
  129. Cython/Includes/cpython/list.pxd +92 -0
  130. Cython/Includes/cpython/long.pxd +149 -0
  131. Cython/Includes/cpython/longintrepr.pxd +14 -0
  132. Cython/Includes/cpython/mapping.pxd +63 -0
  133. Cython/Includes/cpython/marshal.pxd +66 -0
  134. Cython/Includes/cpython/mem.pxd +120 -0
  135. Cython/Includes/cpython/memoryview.pxd +50 -0
  136. Cython/Includes/cpython/method.pxd +49 -0
  137. Cython/Includes/cpython/module.pxd +208 -0
  138. Cython/Includes/cpython/number.pxd +258 -0
  139. Cython/Includes/cpython/object.pxd +433 -0
  140. Cython/Includes/cpython/pycapsule.pxd +143 -0
  141. Cython/Includes/cpython/pylifecycle.pxd +68 -0
  142. Cython/Includes/cpython/pyport.pxd +8 -0
  143. Cython/Includes/cpython/pystate.pxd +95 -0
  144. Cython/Includes/cpython/pythread.pxd +53 -0
  145. Cython/Includes/cpython/ref.pxd +67 -0
  146. Cython/Includes/cpython/sequence.pxd +134 -0
  147. Cython/Includes/cpython/set.pxd +119 -0
  148. Cython/Includes/cpython/slice.pxd +70 -0
  149. Cython/Includes/cpython/time.pxd +129 -0
  150. Cython/Includes/cpython/tuple.pxd +72 -0
  151. Cython/Includes/cpython/type.pxd +53 -0
  152. Cython/Includes/cpython/unicode.pxd +639 -0
  153. Cython/Includes/cpython/version.pxd +32 -0
  154. Cython/Includes/cpython/weakref.pxd +78 -0
  155. Cython/Includes/libc/__init__.pxd +1 -0
  156. Cython/Includes/libc/complex.pxd +35 -0
  157. Cython/Includes/libc/errno.pxd +127 -0
  158. Cython/Includes/libc/float.pxd +43 -0
  159. Cython/Includes/libc/limits.pxd +28 -0
  160. Cython/Includes/libc/locale.pxd +46 -0
  161. Cython/Includes/libc/math.pxd +209 -0
  162. Cython/Includes/libc/setjmp.pxd +10 -0
  163. Cython/Includes/libc/signal.pxd +64 -0
  164. Cython/Includes/libc/stddef.pxd +9 -0
  165. Cython/Includes/libc/stdint.pxd +105 -0
  166. Cython/Includes/libc/stdio.pxd +80 -0
  167. Cython/Includes/libc/stdlib.pxd +72 -0
  168. Cython/Includes/libc/string.pxd +50 -0
  169. Cython/Includes/libc/threads.pxd +84 -0
  170. Cython/Includes/libc/time.pxd +51 -0
  171. Cython/Includes/libcpp/__init__.pxd +4 -0
  172. Cython/Includes/libcpp/algorithm.pxd +320 -0
  173. Cython/Includes/libcpp/any.pxd +16 -0
  174. Cython/Includes/libcpp/atomic.pxd +59 -0
  175. Cython/Includes/libcpp/barrier.pxd +22 -0
  176. Cython/Includes/libcpp/bit.pxd +29 -0
  177. Cython/Includes/libcpp/cast.pxd +12 -0
  178. Cython/Includes/libcpp/cmath.pxd +518 -0
  179. Cython/Includes/libcpp/complex.pxd +106 -0
  180. Cython/Includes/libcpp/deque.pxd +165 -0
  181. Cython/Includes/libcpp/exception.pxd +86 -0
  182. Cython/Includes/libcpp/execution.pxd +15 -0
  183. Cython/Includes/libcpp/forward_list.pxd +63 -0
  184. Cython/Includes/libcpp/functional.pxd +26 -0
  185. Cython/Includes/libcpp/future.pxd +103 -0
  186. Cython/Includes/libcpp/iterator.pxd +34 -0
  187. Cython/Includes/libcpp/latch.pxd +17 -0
  188. Cython/Includes/libcpp/limits.pxd +61 -0
  189. Cython/Includes/libcpp/list.pxd +117 -0
  190. Cython/Includes/libcpp/map.pxd +252 -0
  191. Cython/Includes/libcpp/memory.pxd +115 -0
  192. Cython/Includes/libcpp/mutex.pxd +130 -0
  193. Cython/Includes/libcpp/numbers.pxd +15 -0
  194. Cython/Includes/libcpp/numeric.pxd +131 -0
  195. Cython/Includes/libcpp/optional.pxd +34 -0
  196. Cython/Includes/libcpp/pair.pxd +1 -0
  197. Cython/Includes/libcpp/queue.pxd +25 -0
  198. Cython/Includes/libcpp/random.pxd +166 -0
  199. Cython/Includes/libcpp/semaphore.pxd +44 -0
  200. Cython/Includes/libcpp/set.pxd +228 -0
  201. Cython/Includes/libcpp/shared_mutex.pxd +72 -0
  202. Cython/Includes/libcpp/span.pxd +87 -0
  203. Cython/Includes/libcpp/stack.pxd +11 -0
  204. Cython/Includes/libcpp/stop_token.pxd +105 -0
  205. Cython/Includes/libcpp/string.pxd +355 -0
  206. Cython/Includes/libcpp/string_view.pxd +181 -0
  207. Cython/Includes/libcpp/typeindex.pxd +15 -0
  208. Cython/Includes/libcpp/typeinfo.pxd +10 -0
  209. Cython/Includes/libcpp/unordered_map.pxd +193 -0
  210. Cython/Includes/libcpp/unordered_set.pxd +152 -0
  211. Cython/Includes/libcpp/utility.pxd +30 -0
  212. Cython/Includes/libcpp/vector.pxd +186 -0
  213. Cython/Includes/openmp.pxd +50 -0
  214. Cython/Includes/posix/__init__.pxd +1 -0
  215. Cython/Includes/posix/dlfcn.pxd +14 -0
  216. Cython/Includes/posix/fcntl.pxd +86 -0
  217. Cython/Includes/posix/ioctl.pxd +4 -0
  218. Cython/Includes/posix/mman.pxd +101 -0
  219. Cython/Includes/posix/resource.pxd +57 -0
  220. Cython/Includes/posix/select.pxd +21 -0
  221. Cython/Includes/posix/signal.pxd +73 -0
  222. Cython/Includes/posix/stat.pxd +98 -0
  223. Cython/Includes/posix/stdio.pxd +37 -0
  224. Cython/Includes/posix/stdlib.pxd +29 -0
  225. Cython/Includes/posix/strings.pxd +9 -0
  226. Cython/Includes/posix/time.pxd +71 -0
  227. Cython/Includes/posix/types.pxd +30 -0
  228. Cython/Includes/posix/uio.pxd +26 -0
  229. Cython/Includes/posix/unistd.pxd +271 -0
  230. Cython/Includes/posix/wait.pxd +38 -0
  231. Cython/Plex/Actions.pxd +24 -0
  232. Cython/Plex/Actions.py +119 -0
  233. Cython/Plex/DFA.pxd +14 -0
  234. Cython/Plex/DFA.py +164 -0
  235. Cython/Plex/Errors.py +48 -0
  236. Cython/Plex/Lexicons.py +178 -0
  237. Cython/Plex/Machines.pxd +36 -0
  238. Cython/Plex/Machines.py +238 -0
  239. Cython/Plex/Regexps.py +539 -0
  240. Cython/Plex/Scanners.pxd +47 -0
  241. Cython/Plex/Scanners.py +360 -0
  242. Cython/Plex/Transitions.pxd +14 -0
  243. Cython/Plex/Transitions.py +239 -0
  244. Cython/Plex/__init__.py +34 -0
  245. Cython/Runtime/__init__.py +1 -0
  246. Cython/Runtime/refnanny.pyx +237 -0
  247. Cython/Shadow.py +690 -0
  248. Cython/Shadow.pyi +521 -0
  249. Cython/StringIOTree.py +170 -0
  250. Cython/Tempita/__init__.py +4 -0
  251. Cython/Tempita/_looper.py +154 -0
  252. Cython/Tempita/_tempita.py +1091 -0
  253. Cython/TestUtils.py +410 -0
  254. Cython/Tests/TestCodeWriter.py +128 -0
  255. Cython/Tests/TestCythonUtils.py +202 -0
  256. Cython/Tests/TestJediTyper.py +223 -0
  257. Cython/Tests/TestShadow.py +114 -0
  258. Cython/Tests/TestStringIOTree.py +67 -0
  259. Cython/Tests/TestTestUtils.py +90 -0
  260. Cython/Tests/__init__.py +1 -0
  261. Cython/Tests/xmlrunner.py +390 -0
  262. Cython/Utility/AsyncGen.c +1002 -0
  263. Cython/Utility/Buffer.c +875 -0
  264. Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
  265. Cython/Utility/Builtins.c +776 -0
  266. Cython/Utility/CConvert.pyx +134 -0
  267. Cython/Utility/CMath.c +104 -0
  268. Cython/Utility/CommonStructures.c +118 -0
  269. Cython/Utility/Complex.c +378 -0
  270. Cython/Utility/Coroutine.c +2206 -0
  271. Cython/Utility/CpdefEnums.pyx +103 -0
  272. Cython/Utility/CppConvert.pyx +279 -0
  273. Cython/Utility/CppSupport.cpp +143 -0
  274. Cython/Utility/CythonFunction.c +1794 -0
  275. Cython/Utility/Dataclasses.c +185 -0
  276. Cython/Utility/Dataclasses.py +112 -0
  277. Cython/Utility/Embed.c +125 -0
  278. Cython/Utility/Exceptions.c +1012 -0
  279. Cython/Utility/ExtensionTypes.c +809 -0
  280. Cython/Utility/FunctionArguments.c +965 -0
  281. Cython/Utility/ImportExport.c +987 -0
  282. Cython/Utility/Lock.c +136 -0
  283. Cython/Utility/MemoryView.pxd +187 -0
  284. Cython/Utility/MemoryView.pyx +1481 -0
  285. Cython/Utility/MemoryView_C.c +1046 -0
  286. Cython/Utility/ModuleSetupCode.c +3059 -0
  287. Cython/Utility/NumpyImportArray.c +46 -0
  288. Cython/Utility/ObjectHandling.c +3342 -0
  289. Cython/Utility/Optimize.c +1589 -0
  290. Cython/Utility/Overflow.c +404 -0
  291. Cython/Utility/Printing.c +86 -0
  292. Cython/Utility/Profile.c +709 -0
  293. Cython/Utility/StringTools.c +1259 -0
  294. Cython/Utility/TestCyUtilityLoader.pyx +8 -0
  295. Cython/Utility/TestCythonScope.pyx +75 -0
  296. Cython/Utility/TestUtilityLoader.c +12 -0
  297. Cython/Utility/TypeConversion.c +1284 -0
  298. Cython/Utility/UFuncs.pyx +50 -0
  299. Cython/Utility/UFuncs_C.c +89 -0
  300. Cython/Utility/__init__.py +28 -0
  301. Cython/Utility/arrayarray.h +148 -0
  302. Cython/Utils.py +687 -0
  303. Cython/__init__.py +10 -0
  304. Cython/__init__.pyi +7 -0
  305. Cython/py.typed +0 -0
  306. cython-3.1.0.dist-info/COPYING.txt +19 -0
  307. cython-3.1.0.dist-info/LICENSE.txt +176 -0
  308. cython-3.1.0.dist-info/METADATA +636 -0
  309. cython-3.1.0.dist-info/RECORD +316 -0
  310. cython-3.1.0.dist-info/WHEEL +5 -0
  311. cython-3.1.0.dist-info/entry_points.txt +4 -0
  312. cython-3.1.0.dist-info/top_level.txt +3 -0
  313. cython.py +29 -0
  314. pyximport/__init__.py +4 -0
  315. pyximport/pyxbuild.py +160 -0
  316. pyximport/pyximport.py +482 -0
@@ -0,0 +1,311 @@
1
+ from . import (
2
+ Nodes,
3
+ ExprNodes,
4
+ FusedNode,
5
+ Naming,
6
+ )
7
+ from .Errors import error
8
+ from . import PyrexTypes
9
+ from .UtilityCode import CythonUtilityCode
10
+ from .Code import TempitaUtilityCode, UtilityCode
11
+ from .Visitor import TreeVisitor
12
+ from . import Symtab
13
+
14
+
15
+ class _FindCFuncDefNode(TreeVisitor):
16
+ """
17
+ Finds the CFuncDefNode in the tree
18
+
19
+ The assumption is that there's only one CFuncDefNode
20
+ """
21
+
22
+ found_node = None
23
+
24
+ def visit_Node(self, node):
25
+ if self.found_node:
26
+ return
27
+ else:
28
+ self.visitchildren(node)
29
+
30
+ def visit_CFuncDefNode(self, node):
31
+ self.found_node = node
32
+
33
+ def __call__(self, tree):
34
+ self.visit(tree)
35
+ return self.found_node
36
+
37
+
38
+ def get_cfunc_from_tree(tree):
39
+ return _FindCFuncDefNode()(tree)
40
+
41
+
42
+ class _ArgumentInfo:
43
+ """
44
+ Everything related to defining an input/output argument for a ufunc
45
+
46
+ type - PyrexType
47
+ type_constant - str such as "NPY_INT8" representing numpy dtype constants
48
+ injected_typename - str representing a name that can be used to look up the type
49
+ in Cython code
50
+ """
51
+
52
+ def __init__(self, type, type_constant, injected_typename):
53
+ self.type = type
54
+ self.type_constant = type_constant
55
+ self.injected_typename = injected_typename
56
+
57
+
58
+ class UFuncConversion:
59
+ def __init__(self, node):
60
+ self.node = node
61
+ self.global_scope = node.local_scope.global_scope()
62
+
63
+ self.injected_typename = "ufunc_typename"
64
+ while self.node.entry.cname.startswith(self.injected_typename):
65
+ self.injected_typename += "_"
66
+ self.injected_types = []
67
+ self.in_definitions = self.get_in_type_info()
68
+ self.out_definitions = self.get_out_type_info()
69
+
70
+ def _handle_typedef_type_constant(self, type_, macro_name):
71
+ decl = type_.empty_declaration_code()
72
+ substituted_cname = decl.strip().replace('_', '__').replace(' ', '_')
73
+ context = dict(
74
+ type_substituted_cname=substituted_cname,
75
+ macro_name=macro_name,
76
+ type_cname=decl,
77
+ )
78
+ self.global_scope.use_utility_code(
79
+ TempitaUtilityCode.load(
80
+ 'UFuncTypedef',
81
+ 'UFuncs_C.c',
82
+ context=context
83
+ ))
84
+ return f"__Pyx_typedef_ufunc_{substituted_cname}"
85
+
86
+ def _get_type_constant(self, pos, type_):
87
+ base_type = type_
88
+ if base_type.is_typedef:
89
+ base_type = base_type.typedef_base_type
90
+ base_type = PyrexTypes.remove_cv_ref(base_type)
91
+ if base_type is PyrexTypes.c_bint_type:
92
+ # TODO - this would be nice but not obvious it works
93
+ error(pos, "Type '%s' cannot be used as a ufunc argument" % type_)
94
+ return
95
+ if type_.is_complex:
96
+ return self._handle_typedef_type_constant(
97
+ type_,
98
+ "__PYX_GET_NPY_COMPLEX_TYPE")
99
+ elif type_.is_int:
100
+ signed = ""
101
+ if type_.signed == PyrexTypes.SIGNED:
102
+ signed = "S"
103
+ elif type_.signed == PyrexTypes.UNSIGNED:
104
+ signed = "U"
105
+ return self._handle_typedef_type_constant(
106
+ type_,
107
+ f"__PYX_GET_NPY_{signed}INT_TYPE")
108
+ elif type_.is_float:
109
+ return self._handle_typedef_type_constant(
110
+ type_,
111
+ "__PYX_GET_NPY_FLOAT_TYPE")
112
+ elif type_.is_pyobject:
113
+ return "NPY_OBJECT"
114
+ # TODO possible NPY_BOOL to bint but it needs a cast?
115
+ # TODO NPY_DATETIME, NPY_TIMEDELTA, NPY_STRING, NPY_UNICODE and maybe NPY_VOID might be handleable
116
+ error(pos, "Type '%s' cannot be used as a ufunc argument" % type_)
117
+
118
+ def get_in_type_info(self):
119
+ definitions = []
120
+ for n, arg in enumerate(self.node.args):
121
+ injected_typename = f"{self.injected_typename}_in_{n}"
122
+ self.injected_types.append(injected_typename)
123
+ type_const = self._get_type_constant(self.node.pos, arg.type)
124
+ definitions.append(_ArgumentInfo(arg.type, type_const, injected_typename))
125
+ return definitions
126
+
127
+ def get_out_type_info(self):
128
+ if self.node.return_type.is_ctuple:
129
+ components = self.node.return_type.components
130
+ else:
131
+ components = [self.node.return_type]
132
+ definitions = []
133
+ for n, type in enumerate(components):
134
+ injected_typename = f"{self.injected_typename}_out_{n}"
135
+ self.injected_types.append(injected_typename)
136
+ type_const = self._get_type_constant(self.node.pos, type)
137
+ definitions.append(
138
+ _ArgumentInfo(type, type_const, injected_typename)
139
+ )
140
+ return definitions
141
+
142
+ def generate_cy_utility_code(self):
143
+ arg_types = [(a.injected_typename, a.type) for a in self.in_definitions]
144
+ out_types = [(a.injected_typename, a.type) for a in self.out_definitions]
145
+ context_types = dict(arg_types + out_types)
146
+ self.node.entry.used = True
147
+
148
+ ufunc_cname = self.global_scope.next_id(self.node.entry.name + "_ufunc_def")
149
+
150
+ will_be_called_without_gil = not (any(t.is_pyobject for _, t in arg_types) or
151
+ any(t.is_pyobject for _, t in out_types))
152
+
153
+ context = dict(
154
+ func_cname=ufunc_cname,
155
+ in_types=arg_types,
156
+ out_types=out_types,
157
+ inline_func_call=self.node.entry.cname,
158
+ nogil=self.node.entry.type.nogil,
159
+ will_be_called_without_gil=will_be_called_without_gil,
160
+ **context_types
161
+ )
162
+
163
+ ufunc_global_scope = Symtab.ModuleScope(
164
+ "ufunc_module", None, self.global_scope.context
165
+ )
166
+ ufunc_global_scope.declare_cfunction(
167
+ name=self.node.entry.cname,
168
+ cname=self.node.entry.cname,
169
+ type=self.node.entry.type,
170
+ pos=self.node.pos,
171
+ visibility="extern",
172
+ )
173
+
174
+ code = CythonUtilityCode.load(
175
+ "UFuncDefinition",
176
+ "UFuncs.pyx",
177
+ context=context,
178
+ from_scope = ufunc_global_scope,
179
+ #outer_module_scope=ufunc_global_scope,
180
+ )
181
+
182
+ tree = code.get_tree(entries_only=True)
183
+ return tree
184
+
185
+ def use_generic_utility_code(self):
186
+ # use the invariant C utility code
187
+ self.global_scope.use_utility_code(
188
+ UtilityCode.load_cached("UFuncsInit", "UFuncs_C.c")
189
+ )
190
+ self.global_scope.use_utility_code(
191
+ UtilityCode.load_cached("UFuncTypeHandling", "UFuncs_C.c")
192
+ )
193
+ self.global_scope.use_utility_code(
194
+ UtilityCode.load_cached("NumpyImportUFunc", "NumpyImportArray.c")
195
+ )
196
+
197
+
198
+ def convert_to_ufunc(node):
199
+ if isinstance(node, Nodes.CFuncDefNode):
200
+ if node.local_scope.parent_scope.is_c_class_scope:
201
+ error(node.pos, "Methods cannot currently be converted to a ufunc")
202
+ return node
203
+ converters = [UFuncConversion(node)]
204
+ original_node = node
205
+ elif isinstance(node, FusedNode.FusedCFuncDefNode) and isinstance(
206
+ node.node, Nodes.CFuncDefNode
207
+ ):
208
+ if node.node.local_scope.parent_scope.is_c_class_scope:
209
+ error(node.pos, "Methods cannot currently be converted to a ufunc")
210
+ return node
211
+ converters = [UFuncConversion(n) for n in node.nodes]
212
+ original_node = node.node
213
+ else:
214
+ error(node.pos, "Only C functions can be converted to a ufunc")
215
+ return node
216
+
217
+ if not converters:
218
+ return # this path probably shouldn't happen
219
+
220
+ del converters[0].global_scope.entries[original_node.entry.name]
221
+ # the generic utility code is generic, so there's no reason to do it multiple times
222
+ converters[0].use_generic_utility_code()
223
+ return [node] + _generate_stats_from_converters(converters, original_node)
224
+
225
+
226
+ def generate_ufunc_initialization(converters, cfunc_nodes, original_node):
227
+ global_scope = converters[0].global_scope
228
+ ufunc_funcs_name = global_scope.next_id(Naming.pyrex_prefix + "funcs")
229
+ ufunc_types_name = global_scope.next_id(Naming.pyrex_prefix + "types")
230
+ ufunc_data_name = global_scope.next_id(Naming.pyrex_prefix + "data")
231
+ type_constants = []
232
+ narg_in = None
233
+ narg_out = None
234
+ for c in converters:
235
+ in_const = [d.type_constant for d in c.in_definitions]
236
+ if narg_in is not None:
237
+ assert narg_in == len(in_const)
238
+ else:
239
+ narg_in = len(in_const)
240
+ type_constants.extend(in_const)
241
+ out_const = [d.type_constant for d in c.out_definitions]
242
+ if narg_out is not None:
243
+ assert narg_out == len(out_const)
244
+ else:
245
+ narg_out = len(out_const)
246
+ type_constants.extend(out_const)
247
+
248
+ func_cnames = [cfnode.entry.cname for cfnode in cfunc_nodes]
249
+
250
+ context = dict(
251
+ ufunc_funcs_name=ufunc_funcs_name,
252
+ func_cnames=func_cnames,
253
+ ufunc_types_name=ufunc_types_name,
254
+ type_constants=type_constants,
255
+ ufunc_data_name=ufunc_data_name,
256
+ )
257
+ global_scope.use_utility_code(
258
+ TempitaUtilityCode.load("UFuncConsts", "UFuncs_C.c", context=context)
259
+ )
260
+
261
+ pos = original_node.pos
262
+ func_name = original_node.entry.name
263
+ docstr = original_node.doc
264
+
265
+ args_to_func = '%s(), %s, %s(), %s, %s, %s, PyUFunc_None, "%s", %s, 0' % (
266
+ ufunc_funcs_name,
267
+ ufunc_data_name,
268
+ ufunc_types_name,
269
+ len(func_cnames),
270
+ narg_in,
271
+ narg_out,
272
+ func_name,
273
+ docstr.as_c_string_literal() if docstr else "NULL",
274
+ )
275
+
276
+ call_node = ExprNodes.PythonCapiCallNode(
277
+ pos,
278
+ function_name="PyUFunc_FromFuncAndData",
279
+ # use a dummy type because it's honestly too fiddly
280
+ func_type=PyrexTypes.CFuncType(
281
+ PyrexTypes.py_object_type,
282
+ [PyrexTypes.CFuncTypeArg("dummy", PyrexTypes.c_void_ptr_type, None)],
283
+ ),
284
+ args=[
285
+ ExprNodes.ConstNode(
286
+ pos, type=PyrexTypes.c_void_ptr_type, value=args_to_func
287
+ )
288
+ ],
289
+ )
290
+ lhs_entry = global_scope.declare_var(func_name, PyrexTypes.py_object_type, pos)
291
+ assgn_node = Nodes.SingleAssignmentNode(
292
+ pos,
293
+ lhs=ExprNodes.NameNode(
294
+ pos, name=func_name, type=PyrexTypes.py_object_type, entry=lhs_entry
295
+ ),
296
+ rhs=call_node,
297
+ )
298
+ return assgn_node
299
+
300
+
301
+ def _generate_stats_from_converters(converters, node):
302
+ stats = []
303
+ for converter in converters:
304
+ tree = converter.generate_cy_utility_code()
305
+ ufunc_node = get_cfunc_from_tree(tree)
306
+ # merge in any utility code
307
+ converter.global_scope.utility_code_list.extend(tree.scope.utility_code_list)
308
+ stats.append(ufunc_node)
309
+
310
+ stats.append(generate_ufunc_initialization(converters, stats, node))
311
+ return stats
@@ -0,0 +1,389 @@
1
+ #
2
+ # Nodes used as utilities and support for transforms etc.
3
+ # These often make up sets including both Nodes and ExprNodes
4
+ # so it is convenient to have them in a separate module.
5
+ #
6
+
7
+
8
+ from . import Nodes
9
+ from . import ExprNodes
10
+ from .Nodes import Node
11
+ from .ExprNodes import AtomicExprNode
12
+ from .PyrexTypes import c_ptr_type, c_int_type
13
+
14
+
15
+ class TempHandle:
16
+ # THIS IS DEPRECATED, USE LetRefNode instead
17
+ temp = None
18
+ needs_xdecref = False
19
+ def __init__(self, type, needs_cleanup=None):
20
+ self.type = type
21
+ if needs_cleanup is None:
22
+ self.needs_cleanup = type.is_pyobject
23
+ else:
24
+ self.needs_cleanup = needs_cleanup
25
+
26
+ def ref(self, pos):
27
+ return TempRefNode(pos, handle=self, type=self.type)
28
+
29
+
30
+ class TempRefNode(AtomicExprNode):
31
+ # THIS IS DEPRECATED, USE LetRefNode instead
32
+ # handle TempHandle
33
+
34
+ def analyse_types(self, env):
35
+ assert self.type == self.handle.type
36
+ return self
37
+
38
+ def analyse_target_types(self, env):
39
+ assert self.type == self.handle.type
40
+ return self
41
+
42
+ def analyse_target_declaration(self, env):
43
+ pass
44
+
45
+ def calculate_result_code(self):
46
+ result = self.handle.temp
47
+ if result is None: result = "<error>" # might be called and overwritten
48
+ return result
49
+
50
+ def generate_result_code(self, code):
51
+ pass
52
+
53
+ def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
54
+ if self.type.is_pyobject:
55
+ rhs.make_owned_reference(code)
56
+ # TODO: analyse control flow to see if this is necessary
57
+ code.put_xdecref(self.result(), self.ctype())
58
+ code.putln('%s = %s;' % (
59
+ self.result(),
60
+ rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
61
+ ))
62
+ rhs.generate_post_assignment_code(code)
63
+ rhs.free_temps(code)
64
+
65
+
66
+ class TempsBlockNode(Node):
67
+ # THIS IS DEPRECATED, USE LetNode instead
68
+
69
+ """
70
+ Creates a block which allocates temporary variables.
71
+ This is used by transforms to output constructs that need
72
+ to make use of a temporary variable. Simply pass the types
73
+ of the needed temporaries to the constructor.
74
+
75
+ The variables can be referred to using a TempRefNode
76
+ (which can be constructed by calling get_ref_node).
77
+ """
78
+
79
+ # temps [TempHandle]
80
+ # body StatNode
81
+
82
+ child_attrs = ["body"]
83
+
84
+ def generate_execution_code(self, code):
85
+ for handle in self.temps:
86
+ handle.temp = code.funcstate.allocate_temp(
87
+ handle.type, manage_ref=handle.needs_cleanup)
88
+ self.body.generate_execution_code(code)
89
+ for handle in self.temps:
90
+ if handle.needs_cleanup:
91
+ if handle.needs_xdecref:
92
+ code.put_xdecref_clear(handle.temp, handle.type)
93
+ else:
94
+ code.put_decref_clear(handle.temp, handle.type)
95
+ code.funcstate.release_temp(handle.temp)
96
+
97
+ def analyse_declarations(self, env):
98
+ self.body.analyse_declarations(env)
99
+
100
+ def analyse_expressions(self, env):
101
+ self.body = self.body.analyse_expressions(env)
102
+ return self
103
+
104
+ def generate_function_definitions(self, env, code):
105
+ self.body.generate_function_definitions(env, code)
106
+
107
+ def annotate(self, code):
108
+ self.body.annotate(code)
109
+
110
+
111
+ class ResultRefNode(AtomicExprNode):
112
+ # A reference to the result of an expression. The result_code
113
+ # must be set externally (usually a temp name).
114
+
115
+ subexprs = []
116
+ lhs_of_first_assignment = False
117
+
118
+ def __init__(self, expression=None, pos=None, type=None, may_hold_none=True, is_temp=False):
119
+ self.expression = expression
120
+ self.pos = None
121
+ self.may_hold_none = may_hold_none
122
+ if expression is not None:
123
+ self.pos = expression.pos
124
+ self.type = getattr(expression, "type", None)
125
+ if pos is not None:
126
+ self.pos = pos
127
+ if type is not None:
128
+ self.type = type
129
+ if is_temp:
130
+ self.is_temp = True
131
+ assert self.pos is not None
132
+
133
+ def clone_node(self):
134
+ # nothing to do here
135
+ return self
136
+
137
+ def type_dependencies(self, env):
138
+ if self.expression:
139
+ return self.expression.type_dependencies(env)
140
+ else:
141
+ return ()
142
+
143
+ def update_expression(self, expression):
144
+ self.expression = expression
145
+ type = getattr(expression, "type", None)
146
+ if type:
147
+ self.type = type
148
+
149
+ def analyse_target_declaration(self, env):
150
+ pass # OK - we can assign to this
151
+
152
+ def analyse_types(self, env):
153
+ if self.expression is not None:
154
+ if not self.expression.type:
155
+ self.expression = self.expression.analyse_types(env)
156
+ self.type = self.expression.type
157
+ return self
158
+
159
+ def infer_type(self, env):
160
+ if self.type is not None:
161
+ return self.type
162
+ if self.expression is not None:
163
+ if self.expression.type is not None:
164
+ return self.expression.type
165
+ return self.expression.infer_type(env)
166
+ assert False, "cannot infer type of ResultRefNode"
167
+
168
+ def may_be_none(self):
169
+ if not self.type.is_pyobject:
170
+ return False
171
+ return self.may_hold_none
172
+
173
+ def _DISABLED_may_be_none(self):
174
+ # not sure if this is safe - the expression may not be the
175
+ # only value that gets assigned
176
+ if self.expression is not None:
177
+ return self.expression.may_be_none()
178
+ if self.type is not None:
179
+ return self.type.is_pyobject
180
+ return True # play it safe
181
+
182
+ def is_simple(self):
183
+ return True
184
+
185
+ def result(self):
186
+ try:
187
+ return self.result_code
188
+ except AttributeError:
189
+ if self.expression is not None:
190
+ self.result_code = self.expression.result()
191
+ return self.result_code
192
+
193
+ def generate_evaluation_code(self, code):
194
+ pass
195
+
196
+ def generate_result_code(self, code):
197
+ pass
198
+
199
+ def generate_disposal_code(self, code):
200
+ pass
201
+
202
+ def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
203
+ if self.type.is_pyobject:
204
+ rhs.make_owned_reference(code)
205
+ if not self.lhs_of_first_assignment:
206
+ code.put_decref(self.result(), self.ctype())
207
+ code.putln('%s = %s;' % (
208
+ self.result(),
209
+ rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
210
+ ))
211
+ rhs.generate_post_assignment_code(code)
212
+ rhs.free_temps(code)
213
+
214
+ def allocate_temps(self, env):
215
+ pass
216
+
217
+ def release_temp(self, env):
218
+ pass
219
+
220
+ def free_temps(self, code):
221
+ pass
222
+
223
+
224
+ class LetNodeMixin:
225
+ def set_temp_expr(self, lazy_temp):
226
+ self.lazy_temp = lazy_temp
227
+ self.temp_expression = lazy_temp.expression
228
+
229
+ def setup_temp_expr(self, code):
230
+ self.temp_expression.generate_evaluation_code(code)
231
+ self.temp_type = self.temp_expression.type
232
+ if self.temp_type.is_array:
233
+ self.temp_type = c_ptr_type(self.temp_type.base_type)
234
+ self._result_in_temp = self.temp_expression.result_in_temp()
235
+ if self._result_in_temp:
236
+ self.temp = self.temp_expression.result()
237
+ else:
238
+ if self.temp_type.is_memoryviewslice:
239
+ self.temp_expression.make_owned_memoryviewslice(code)
240
+ else:
241
+ self.temp_expression.make_owned_reference(code)
242
+ self.temp = code.funcstate.allocate_temp(
243
+ self.temp_type, manage_ref=True)
244
+ code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
245
+ self.temp_expression.generate_disposal_code(code)
246
+ self.temp_expression.free_temps(code)
247
+ self.lazy_temp.result_code = self.temp
248
+
249
+ def teardown_temp_expr(self, code):
250
+ if self._result_in_temp:
251
+ self.temp_expression.generate_disposal_code(code)
252
+ self.temp_expression.free_temps(code)
253
+ else:
254
+ if self.temp_type.needs_refcounting:
255
+ code.put_decref_clear(self.temp, self.temp_type)
256
+ code.funcstate.release_temp(self.temp)
257
+
258
+
259
+ class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
260
+ # A wrapper around a subexpression that moves an expression into a
261
+ # temp variable and provides it to the subexpression.
262
+
263
+ subexprs = ['temp_expression', 'subexpression']
264
+
265
+ def __init__(self, lazy_temp, subexpression):
266
+ self.set_temp_expr(lazy_temp)
267
+ self.pos = subexpression.pos
268
+ self.subexpression = subexpression
269
+ # if called after type analysis, we already know the type here
270
+ self.type = self.subexpression.type
271
+
272
+ def infer_type(self, env):
273
+ return self.subexpression.infer_type(env)
274
+
275
+ def may_be_none(self):
276
+ return self.subexpression.may_be_none()
277
+
278
+ def result(self):
279
+ return self.subexpression.result()
280
+
281
+ def analyse_types(self, env):
282
+ self.temp_expression = self.temp_expression.analyse_types(env)
283
+ self.lazy_temp.update_expression(self.temp_expression) # overwrite in case it changed
284
+ self.subexpression = self.subexpression.analyse_types(env)
285
+ self.type = self.subexpression.type
286
+ return self
287
+
288
+ def free_subexpr_temps(self, code):
289
+ self.subexpression.free_temps(code)
290
+
291
+ def generate_subexpr_disposal_code(self, code):
292
+ self.subexpression.generate_disposal_code(code)
293
+
294
+ def generate_evaluation_code(self, code):
295
+ self.setup_temp_expr(code)
296
+ self.subexpression.generate_evaluation_code(code)
297
+ self.teardown_temp_expr(code)
298
+
299
+
300
+ LetRefNode = ResultRefNode
301
+
302
+
303
+ class LetNode(Nodes.StatNode, LetNodeMixin):
304
+ # Implements a local temporary variable scope. Imagine this
305
+ # syntax being present:
306
+ # let temp = VALUE:
307
+ # BLOCK (can modify temp)
308
+ # if temp is an object, decref
309
+ #
310
+ # Usually used after analysis phase, but forwards analysis methods
311
+ # to its children
312
+
313
+ child_attrs = ['temp_expression', 'body']
314
+
315
+ def __init__(self, lazy_temp, body):
316
+ self.set_temp_expr(lazy_temp)
317
+ self.pos = body.pos
318
+ self.body = body
319
+
320
+ def analyse_declarations(self, env):
321
+ self.temp_expression.analyse_declarations(env)
322
+ self.body.analyse_declarations(env)
323
+
324
+ def analyse_expressions(self, env):
325
+ self.temp_expression = self.temp_expression.analyse_expressions(env)
326
+ self.body = self.body.analyse_expressions(env)
327
+ return self
328
+
329
+ def generate_execution_code(self, code):
330
+ self.setup_temp_expr(code)
331
+ self.body.generate_execution_code(code)
332
+ self.teardown_temp_expr(code)
333
+
334
+ def generate_function_definitions(self, env, code):
335
+ self.temp_expression.generate_function_definitions(env, code)
336
+ self.body.generate_function_definitions(env, code)
337
+
338
+
339
+ class TempResultFromStatNode(ExprNodes.ExprNode):
340
+ # An ExprNode wrapper around a StatNode that executes the StatNode
341
+ # body. Requires a ResultRefNode that it sets up to refer to its
342
+ # own temp result. The StatNode must assign a value to the result
343
+ # node, which then becomes the result of this node.
344
+
345
+ subexprs = []
346
+ child_attrs = ['body']
347
+
348
+ def __init__(self, result_ref, body):
349
+ self.result_ref = result_ref
350
+ self.pos = body.pos
351
+ self.body = body
352
+ self.type = result_ref.type
353
+ self.is_temp = 1
354
+
355
+ def analyse_declarations(self, env):
356
+ self.body.analyse_declarations(env)
357
+
358
+ def analyse_types(self, env):
359
+ self.body = self.body.analyse_expressions(env)
360
+ return self
361
+
362
+ def may_be_none(self):
363
+ return self.result_ref.may_be_none()
364
+
365
+ def generate_result_code(self, code):
366
+ self.result_ref.result_code = self.result()
367
+ self.body.generate_execution_code(code)
368
+
369
+ def generate_function_definitions(self, env, code):
370
+ self.body.generate_function_definitions(env, code)
371
+
372
+
373
+ class HasNoGilNode(AtomicExprNode):
374
+ """
375
+ Simple node that evaluates to
376
+ * 0 if gil
377
+ * 1 if nogil
378
+ * 2 if maybe gil
379
+ """
380
+ type = c_int_type
381
+
382
+ def analyse_types(self, env):
383
+ return self
384
+
385
+ def generate_result_code(self, code):
386
+ pass
387
+
388
+ def calculate_result_code(self):
389
+ return str(int(self.in_nogil_context))