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.
- Cython/Build/BuildExecutable.py +169 -0
- Cython/Build/Cache.py +199 -0
- Cython/Build/Cythonize.py +323 -0
- Cython/Build/Dependencies.py +1306 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +463 -0
- Cython/Build/IpythonMagic.py +560 -0
- Cython/Build/SharedModule.py +76 -0
- Cython/Build/Tests/TestCyCache.py +194 -0
- Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
- Cython/Build/Tests/TestDependencies.py +133 -0
- Cython/Build/Tests/TestInline.py +177 -0
- Cython/Build/Tests/TestIpythonMagic.py +287 -0
- Cython/Build/Tests/TestRecythonize.py +212 -0
- Cython/Build/Tests/TestStripLiterals.py +155 -0
- Cython/Build/Tests/__init__.py +1 -0
- Cython/Build/__init__.py +8 -0
- Cython/CodeWriter.py +811 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +326 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +934 -0
- Cython/Compiler/CmdLine.py +259 -0
- Cython/Compiler/Code.pxd +148 -0
- Cython/Compiler/Code.py +3375 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +187 -0
- Cython/Compiler/Dataclass.py +868 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +295 -0
- Cython/Compiler/ExprNodes.py +15267 -0
- Cython/Compiler/FlowControl.pxd +97 -0
- Cython/Compiler/FlowControl.py +1455 -0
- Cython/Compiler/FusedNode.py +1002 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +340 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/Main.py +853 -0
- Cython/Compiler/MatchCaseNodes.py +259 -0
- Cython/Compiler/MemoryView.py +922 -0
- Cython/Compiler/ModuleNode.py +4024 -0
- Cython/Compiler/Naming.py +374 -0
- Cython/Compiler/Nodes.py +10826 -0
- Cython/Compiler/Optimize.py +5256 -0
- Cython/Compiler/Options.py +835 -0
- Cython/Compiler/ParseTreeTransforms.pxd +77 -0
- Cython/Compiler/ParseTreeTransforms.py +4509 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4789 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +5762 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.pxd +40 -0
- Cython/Compiler/Scanning.py +577 -0
- Cython/Compiler/StringEncoding.py +347 -0
- Cython/Compiler/Symtab.py +3080 -0
- Cython/Compiler/Tests/TestBuffer.py +105 -0
- Cython/Compiler/Tests/TestBuiltin.py +72 -0
- Cython/Compiler/Tests/TestCmdLine.py +586 -0
- Cython/Compiler/Tests/TestCode.py +86 -0
- Cython/Compiler/Tests/TestFlowControl.py +65 -0
- Cython/Compiler/Tests/TestGrammar.py +202 -0
- Cython/Compiler/Tests/TestMemView.py +71 -0
- Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
- Cython/Compiler/Tests/TestScanning.py +134 -0
- Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
- Cython/Compiler/Tests/TestStringEncoding.py +33 -0
- Cython/Compiler/Tests/TestTreeFragment.py +63 -0
- Cython/Compiler/Tests/TestTreePath.py +103 -0
- Cython/Compiler/Tests/TestTypes.py +75 -0
- Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
- Cython/Compiler/Tests/TestVisitor.py +61 -0
- Cython/Compiler/Tests/Utils.py +36 -0
- Cython/Compiler/Tests/__init__.py +1 -0
- Cython/Compiler/TreeFragment.py +278 -0
- Cython/Compiler/TreePath.py +303 -0
- Cython/Compiler/TypeInference.py +584 -0
- Cython/Compiler/TypeSlots.py +1181 -0
- Cython/Compiler/UFuncs.py +311 -0
- Cython/Compiler/UtilNodes.py +389 -0
- Cython/Compiler/UtilityCode.py +344 -0
- Cython/Compiler/Version.py +8 -0
- Cython/Compiler/Visitor.pxd +53 -0
- Cython/Compiler/Visitor.py +861 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +175 -0
- Cython/Debugger/DebugWriter.py +82 -0
- Cython/Debugger/Tests/TestLibCython.py +275 -0
- Cython/Debugger/Tests/__init__.py +1 -0
- Cython/Debugger/Tests/cfuncs.c +8 -0
- Cython/Debugger/Tests/codefile +49 -0
- Cython/Debugger/Tests/test_libcython_in_gdb.py +578 -0
- Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
- Cython/Debugger/__init__.py +1 -0
- Cython/Debugger/libcython.py +1548 -0
- Cython/Debugger/libpython.py +2821 -0
- Cython/Debugging.py +20 -0
- Cython/Distutils/__init__.py +2 -0
- Cython/Distutils/build_ext.py +139 -0
- Cython/Distutils/extension.py +96 -0
- Cython/Distutils/old_build_ext.py +351 -0
- Cython/Includes/cpython/__init__.pxd +173 -0
- Cython/Includes/cpython/array.pxd +174 -0
- Cython/Includes/cpython/bool.pxd +37 -0
- Cython/Includes/cpython/buffer.pxd +112 -0
- Cython/Includes/cpython/bytearray.pxd +33 -0
- Cython/Includes/cpython/bytes.pxd +200 -0
- Cython/Includes/cpython/cellobject.pxd +35 -0
- Cython/Includes/cpython/ceval.pxd +8 -0
- Cython/Includes/cpython/codecs.pxd +121 -0
- Cython/Includes/cpython/complex.pxd +60 -0
- Cython/Includes/cpython/contextvars.pxd +145 -0
- Cython/Includes/cpython/conversion.pxd +36 -0
- Cython/Includes/cpython/datetime.pxd +395 -0
- Cython/Includes/cpython/descr.pxd +26 -0
- Cython/Includes/cpython/dict.pxd +187 -0
- Cython/Includes/cpython/exc.pxd +263 -0
- Cython/Includes/cpython/fileobject.pxd +57 -0
- Cython/Includes/cpython/float.pxd +47 -0
- Cython/Includes/cpython/function.pxd +65 -0
- Cython/Includes/cpython/genobject.pxd +25 -0
- Cython/Includes/cpython/getargs.pxd +12 -0
- Cython/Includes/cpython/instance.pxd +25 -0
- Cython/Includes/cpython/iterator.pxd +36 -0
- Cython/Includes/cpython/iterobject.pxd +24 -0
- Cython/Includes/cpython/list.pxd +92 -0
- Cython/Includes/cpython/long.pxd +149 -0
- Cython/Includes/cpython/longintrepr.pxd +14 -0
- Cython/Includes/cpython/mapping.pxd +63 -0
- Cython/Includes/cpython/marshal.pxd +66 -0
- Cython/Includes/cpython/mem.pxd +120 -0
- Cython/Includes/cpython/memoryview.pxd +50 -0
- Cython/Includes/cpython/method.pxd +49 -0
- Cython/Includes/cpython/module.pxd +208 -0
- Cython/Includes/cpython/number.pxd +258 -0
- Cython/Includes/cpython/object.pxd +433 -0
- Cython/Includes/cpython/pycapsule.pxd +143 -0
- Cython/Includes/cpython/pylifecycle.pxd +68 -0
- Cython/Includes/cpython/pyport.pxd +8 -0
- Cython/Includes/cpython/pystate.pxd +95 -0
- Cython/Includes/cpython/pythread.pxd +53 -0
- Cython/Includes/cpython/ref.pxd +67 -0
- Cython/Includes/cpython/sequence.pxd +134 -0
- Cython/Includes/cpython/set.pxd +119 -0
- Cython/Includes/cpython/slice.pxd +70 -0
- Cython/Includes/cpython/time.pxd +129 -0
- Cython/Includes/cpython/tuple.pxd +72 -0
- Cython/Includes/cpython/type.pxd +53 -0
- Cython/Includes/cpython/unicode.pxd +639 -0
- Cython/Includes/cpython/version.pxd +32 -0
- Cython/Includes/cpython/weakref.pxd +78 -0
- Cython/Includes/libc/__init__.pxd +1 -0
- Cython/Includes/libc/complex.pxd +35 -0
- Cython/Includes/libc/errno.pxd +127 -0
- Cython/Includes/libc/float.pxd +43 -0
- Cython/Includes/libc/limits.pxd +28 -0
- Cython/Includes/libc/locale.pxd +46 -0
- Cython/Includes/libc/math.pxd +209 -0
- Cython/Includes/libc/setjmp.pxd +10 -0
- Cython/Includes/libc/signal.pxd +64 -0
- Cython/Includes/libc/stddef.pxd +9 -0
- Cython/Includes/libc/stdint.pxd +105 -0
- Cython/Includes/libc/stdio.pxd +80 -0
- Cython/Includes/libc/stdlib.pxd +72 -0
- Cython/Includes/libc/string.pxd +50 -0
- Cython/Includes/libc/threads.pxd +84 -0
- Cython/Includes/libc/time.pxd +51 -0
- Cython/Includes/libcpp/__init__.pxd +4 -0
- Cython/Includes/libcpp/algorithm.pxd +320 -0
- Cython/Includes/libcpp/any.pxd +16 -0
- Cython/Includes/libcpp/atomic.pxd +59 -0
- Cython/Includes/libcpp/barrier.pxd +22 -0
- Cython/Includes/libcpp/bit.pxd +29 -0
- Cython/Includes/libcpp/cast.pxd +12 -0
- Cython/Includes/libcpp/cmath.pxd +518 -0
- Cython/Includes/libcpp/complex.pxd +106 -0
- Cython/Includes/libcpp/deque.pxd +165 -0
- Cython/Includes/libcpp/exception.pxd +86 -0
- Cython/Includes/libcpp/execution.pxd +15 -0
- Cython/Includes/libcpp/forward_list.pxd +63 -0
- Cython/Includes/libcpp/functional.pxd +26 -0
- Cython/Includes/libcpp/future.pxd +103 -0
- Cython/Includes/libcpp/iterator.pxd +34 -0
- Cython/Includes/libcpp/latch.pxd +17 -0
- Cython/Includes/libcpp/limits.pxd +61 -0
- Cython/Includes/libcpp/list.pxd +117 -0
- Cython/Includes/libcpp/map.pxd +252 -0
- Cython/Includes/libcpp/memory.pxd +115 -0
- Cython/Includes/libcpp/mutex.pxd +130 -0
- Cython/Includes/libcpp/numbers.pxd +15 -0
- Cython/Includes/libcpp/numeric.pxd +131 -0
- Cython/Includes/libcpp/optional.pxd +34 -0
- Cython/Includes/libcpp/pair.pxd +1 -0
- Cython/Includes/libcpp/queue.pxd +25 -0
- Cython/Includes/libcpp/random.pxd +166 -0
- Cython/Includes/libcpp/semaphore.pxd +44 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +72 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +105 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +181 -0
- Cython/Includes/libcpp/typeindex.pxd +15 -0
- Cython/Includes/libcpp/typeinfo.pxd +10 -0
- Cython/Includes/libcpp/unordered_map.pxd +193 -0
- Cython/Includes/libcpp/unordered_set.pxd +152 -0
- Cython/Includes/libcpp/utility.pxd +30 -0
- Cython/Includes/libcpp/vector.pxd +186 -0
- Cython/Includes/openmp.pxd +50 -0
- Cython/Includes/posix/__init__.pxd +1 -0
- Cython/Includes/posix/dlfcn.pxd +14 -0
- Cython/Includes/posix/fcntl.pxd +86 -0
- Cython/Includes/posix/ioctl.pxd +4 -0
- Cython/Includes/posix/mman.pxd +101 -0
- Cython/Includes/posix/resource.pxd +57 -0
- Cython/Includes/posix/select.pxd +21 -0
- Cython/Includes/posix/signal.pxd +73 -0
- Cython/Includes/posix/stat.pxd +98 -0
- Cython/Includes/posix/stdio.pxd +37 -0
- Cython/Includes/posix/stdlib.pxd +29 -0
- Cython/Includes/posix/strings.pxd +9 -0
- Cython/Includes/posix/time.pxd +71 -0
- Cython/Includes/posix/types.pxd +30 -0
- Cython/Includes/posix/uio.pxd +26 -0
- Cython/Includes/posix/unistd.pxd +271 -0
- Cython/Includes/posix/wait.pxd +38 -0
- Cython/Plex/Actions.pxd +24 -0
- Cython/Plex/Actions.py +119 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/Errors.py +48 -0
- Cython/Plex/Lexicons.py +178 -0
- Cython/Plex/Machines.pxd +36 -0
- Cython/Plex/Machines.py +238 -0
- Cython/Plex/Regexps.py +539 -0
- Cython/Plex/Scanners.pxd +47 -0
- Cython/Plex/Scanners.py +360 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +690 -0
- Cython/Shadow.pyi +521 -0
- Cython/StringIOTree.py +170 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.py +1091 -0
- Cython/TestUtils.py +410 -0
- Cython/Tests/TestCodeWriter.py +128 -0
- Cython/Tests/TestCythonUtils.py +202 -0
- Cython/Tests/TestJediTyper.py +223 -0
- Cython/Tests/TestShadow.py +114 -0
- Cython/Tests/TestStringIOTree.py +67 -0
- Cython/Tests/TestTestUtils.py +90 -0
- Cython/Tests/__init__.py +1 -0
- Cython/Tests/xmlrunner.py +390 -0
- Cython/Utility/AsyncGen.c +1002 -0
- Cython/Utility/Buffer.c +875 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +776 -0
- Cython/Utility/CConvert.pyx +134 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +118 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2206 -0
- Cython/Utility/CpdefEnums.pyx +103 -0
- Cython/Utility/CppConvert.pyx +279 -0
- Cython/Utility/CppSupport.cpp +143 -0
- Cython/Utility/CythonFunction.c +1794 -0
- Cython/Utility/Dataclasses.c +185 -0
- Cython/Utility/Dataclasses.py +112 -0
- Cython/Utility/Embed.c +125 -0
- Cython/Utility/Exceptions.c +1012 -0
- Cython/Utility/ExtensionTypes.c +809 -0
- Cython/Utility/FunctionArguments.c +965 -0
- Cython/Utility/ImportExport.c +987 -0
- Cython/Utility/Lock.c +136 -0
- Cython/Utility/MemoryView.pxd +187 -0
- Cython/Utility/MemoryView.pyx +1481 -0
- Cython/Utility/MemoryView_C.c +1046 -0
- Cython/Utility/ModuleSetupCode.c +3059 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3342 -0
- Cython/Utility/Optimize.c +1589 -0
- Cython/Utility/Overflow.c +404 -0
- Cython/Utility/Printing.c +86 -0
- Cython/Utility/Profile.c +709 -0
- Cython/Utility/StringTools.c +1259 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1284 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +148 -0
- Cython/Utils.py +687 -0
- Cython/__init__.py +10 -0
- Cython/__init__.pyi +7 -0
- Cython/py.typed +0 -0
- cython-3.1.0.dist-info/COPYING.txt +19 -0
- cython-3.1.0.dist-info/LICENSE.txt +176 -0
- cython-3.1.0.dist-info/METADATA +636 -0
- cython-3.1.0.dist-info/RECORD +316 -0
- cython-3.1.0.dist-info/WHEEL +5 -0
- cython-3.1.0.dist-info/entry_points.txt +4 -0
- cython-3.1.0.dist-info/top_level.txt +3 -0
- cython.py +29 -0
- pyximport/__init__.py +4 -0
- pyximport/pyxbuild.py +160 -0
- 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))
|