Cython 3.2.0__cp39-abi3-win32.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 +350 -0
- Cython/Build/Dependencies.py +1314 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +463 -0
- Cython/Build/IpythonMagic.py +560 -0
- Cython/Build/SharedModule.py +94 -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 +11 -0
- Cython/CodeWriter.py +815 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +328 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +984 -0
- Cython/Compiler/CmdLine.py +263 -0
- Cython/Compiler/Code.pxd +149 -0
- Cython/Compiler/Code.py +3746 -0
- Cython/Compiler/Code.pyd +0 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +191 -0
- Cython/Compiler/Dataclass.py +864 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +297 -0
- Cython/Compiler/ExprNodes.py +15562 -0
- Cython/Compiler/FlowControl.pxd +97 -0
- Cython/Compiler/FlowControl.py +1451 -0
- Cython/Compiler/FlowControl.pyd +0 -0
- Cython/Compiler/FusedNode.py +971 -0
- Cython/Compiler/FusedNode.pyd +0 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +421 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/LineTable.pyd +0 -0
- Cython/Compiler/Main.py +857 -0
- Cython/Compiler/MatchCaseNodes.py +259 -0
- Cython/Compiler/MemoryView.py +905 -0
- Cython/Compiler/ModuleNode.py +4235 -0
- Cython/Compiler/Naming.py +363 -0
- Cython/Compiler/Nodes.py +10831 -0
- Cython/Compiler/Optimize.py +5288 -0
- Cython/Compiler/Options.py +843 -0
- Cython/Compiler/ParseTreeTransforms.pxd +78 -0
- Cython/Compiler/ParseTreeTransforms.py +4638 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4775 -0
- Cython/Compiler/Parsing.pyd +0 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +5870 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.pxd +48 -0
- Cython/Compiler/Scanning.py +701 -0
- Cython/Compiler/Scanning.pyd +0 -0
- Cython/Compiler/StringEncoding.py +298 -0
- Cython/Compiler/Symtab.py +3073 -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 +144 -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 +21 -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 +591 -0
- Cython/Compiler/TypeSlots.py +1174 -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/Visitor.pyd +0 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +177 -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 +178 -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 +141 -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 +234 -0
- Cython/Includes/libc/time.pxd +52 -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/condition_variable.pxd +322 -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 +387 -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 +43 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +96 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +117 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +183 -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/numpy/math.pxd +150 -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/Actions.pyd +0 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/DFA.pyd +0 -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/Machines.pyd +0 -0
- Cython/Plex/Regexps.py +535 -0
- Cython/Plex/Scanners.pxd +45 -0
- Cython/Plex/Scanners.py +328 -0
- Cython/Plex/Scanners.pyd +0 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/Transitions.pyd +0 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.pyd +0 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +690 -0
- Cython/Shadow.pyi +521 -0
- Cython/StringIOTree.py +170 -0
- Cython/StringIOTree.pyd +0 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.py +1091 -0
- Cython/Tempita/_tempita.pyd +0 -0
- Cython/TestUtils.py +422 -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 +1031 -0
- Cython/Utility/Buffer.c +865 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +810 -0
- Cython/Utility/CConvert.pyx +134 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +226 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2300 -0
- Cython/Utility/CpdefEnums.pyx +103 -0
- Cython/Utility/CppConvert.pyx +282 -0
- Cython/Utility/CppSupport.cpp +151 -0
- Cython/Utility/CythonFunction.c +1832 -0
- Cython/Utility/Dataclasses.c +101 -0
- Cython/Utility/Embed.c +121 -0
- Cython/Utility/Exceptions.c +1016 -0
- Cython/Utility/ExtensionTypes.c +996 -0
- Cython/Utility/FunctionArguments.c +1043 -0
- Cython/Utility/FusedFunction.pyx +44 -0
- Cython/Utility/ImportExport.c +907 -0
- Cython/Utility/MemoryView.pxd +188 -0
- Cython/Utility/MemoryView.pyx +1482 -0
- Cython/Utility/MemoryView_C.c +927 -0
- Cython/Utility/ModuleSetupCode.c +3203 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3273 -0
- Cython/Utility/Optimize.c +1603 -0
- Cython/Utility/Overflow.c +384 -0
- Cython/Utility/Printing.c +86 -0
- Cython/Utility/Profile.c +732 -0
- Cython/Utility/StringTools.c +1379 -0
- Cython/Utility/Synchronization.c +399 -0
- Cython/Utility/TString.c +356 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1385 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +167 -0
- Cython/Utils.py +687 -0
- Cython/Utils.pyd +0 -0
- Cython/__init__.py +10 -0
- Cython/__init__.pyi +7 -0
- Cython/py.typed +0 -0
- cython-3.2.0.dist-info/METADATA +85 -0
- cython-3.2.0.dist-info/RECORD +333 -0
- cython-3.2.0.dist-info/WHEEL +5 -0
- cython-3.2.0.dist-info/entry_points.txt +4 -0
- cython-3.2.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,591 @@
|
|
|
1
|
+
from .Errors import error, message
|
|
2
|
+
from . import ExprNodes
|
|
3
|
+
from . import Nodes
|
|
4
|
+
from . import Builtin
|
|
5
|
+
from . import PyrexTypes
|
|
6
|
+
from .. import Utils
|
|
7
|
+
from .PyrexTypes import py_object_type, unspecified_type
|
|
8
|
+
from .Visitor import CythonTransform, EnvTransform
|
|
9
|
+
|
|
10
|
+
from functools import reduce
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TypedExprNode(ExprNodes.ExprNode):
|
|
14
|
+
# Used for declaring assignments of a specified type without a known entry.
|
|
15
|
+
subexprs = []
|
|
16
|
+
|
|
17
|
+
def __init__(self, type, pos=None):
|
|
18
|
+
super().__init__(pos, type=type)
|
|
19
|
+
|
|
20
|
+
object_expr = TypedExprNode(py_object_type)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MarkParallelAssignments(EnvTransform):
|
|
24
|
+
# Collects assignments inside parallel blocks prange, with parallel.
|
|
25
|
+
# Perhaps it's better to move it to ControlFlowAnalysis.
|
|
26
|
+
|
|
27
|
+
# tells us whether we're in a normal loop
|
|
28
|
+
in_loop = False
|
|
29
|
+
|
|
30
|
+
parallel_errors = False
|
|
31
|
+
|
|
32
|
+
def __init__(self, context):
|
|
33
|
+
# Track the parallel block scopes (with parallel, for i in prange())
|
|
34
|
+
self.parallel_block_stack = []
|
|
35
|
+
super().__init__(context)
|
|
36
|
+
|
|
37
|
+
def mark_assignment(self, lhs, rhs, inplace_op=None):
|
|
38
|
+
if isinstance(lhs, (ExprNodes.NameNode, Nodes.PyArgDeclNode)):
|
|
39
|
+
if lhs.entry is None:
|
|
40
|
+
# TODO: This shouldn't happen...
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
if self.parallel_block_stack:
|
|
44
|
+
parallel_node = self.parallel_block_stack[-1]
|
|
45
|
+
previous_assignment = parallel_node.assignments.get(lhs.entry)
|
|
46
|
+
|
|
47
|
+
# If there was a previous assignment to the variable, keep the
|
|
48
|
+
# previous assignment position
|
|
49
|
+
if previous_assignment:
|
|
50
|
+
pos, previous_inplace_op = previous_assignment
|
|
51
|
+
|
|
52
|
+
if (inplace_op and previous_inplace_op and
|
|
53
|
+
inplace_op != previous_inplace_op):
|
|
54
|
+
# x += y; x *= y
|
|
55
|
+
t = (inplace_op, previous_inplace_op)
|
|
56
|
+
error(lhs.pos,
|
|
57
|
+
"Reduction operator '%s' is inconsistent "
|
|
58
|
+
"with previous reduction operator '%s'" % t)
|
|
59
|
+
else:
|
|
60
|
+
pos = lhs.pos
|
|
61
|
+
|
|
62
|
+
parallel_node.assignments[lhs.entry] = (pos, inplace_op)
|
|
63
|
+
parallel_node.assigned_nodes.append(lhs)
|
|
64
|
+
|
|
65
|
+
elif isinstance(lhs, ExprNodes.SequenceNode):
|
|
66
|
+
for i, arg in enumerate(lhs.args):
|
|
67
|
+
if not rhs or arg.is_starred:
|
|
68
|
+
item_node = None
|
|
69
|
+
else:
|
|
70
|
+
item_node = rhs.inferable_item_node(i)
|
|
71
|
+
self.mark_assignment(arg, item_node)
|
|
72
|
+
else:
|
|
73
|
+
# Could use this info to infer cdef class attributes...
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
def visit_WithTargetAssignmentStatNode(self, node):
|
|
77
|
+
self.mark_assignment(node.lhs, node.with_node.enter_call)
|
|
78
|
+
self.visitchildren(node)
|
|
79
|
+
return node
|
|
80
|
+
|
|
81
|
+
def visit_SingleAssignmentNode(self, node):
|
|
82
|
+
if self.parallel_block_stack:
|
|
83
|
+
node.in_parallel_block = True
|
|
84
|
+
self.mark_assignment(node.lhs, node.rhs)
|
|
85
|
+
self.visitchildren(node)
|
|
86
|
+
return node
|
|
87
|
+
|
|
88
|
+
def visit_CascadedAssignmentNode(self, node):
|
|
89
|
+
for lhs in node.lhs_list:
|
|
90
|
+
self.mark_assignment(lhs, node.rhs)
|
|
91
|
+
self.visitchildren(node)
|
|
92
|
+
return node
|
|
93
|
+
|
|
94
|
+
def visit_InPlaceAssignmentNode(self, node):
|
|
95
|
+
self.mark_assignment(node.lhs, node.create_binop_node(), node.operator)
|
|
96
|
+
self.visitchildren(node)
|
|
97
|
+
return node
|
|
98
|
+
|
|
99
|
+
def visit_ForInStatNode(self, node):
|
|
100
|
+
# TODO: Remove redundancy with range optimization...
|
|
101
|
+
is_special = False
|
|
102
|
+
sequence = node.iterator.sequence
|
|
103
|
+
target = node.target
|
|
104
|
+
iterator_scope = node.iterator.expr_scope or self.current_env()
|
|
105
|
+
if isinstance(sequence, ExprNodes.SimpleCallNode):
|
|
106
|
+
function = sequence.function
|
|
107
|
+
if sequence.self is None and function.is_name:
|
|
108
|
+
entry = iterator_scope.lookup(function.name)
|
|
109
|
+
if not entry or entry.is_builtin:
|
|
110
|
+
if function.name == 'reversed' and len(sequence.args) == 1:
|
|
111
|
+
sequence = sequence.args[0]
|
|
112
|
+
elif function.name == 'enumerate' and len(sequence.args) == 1:
|
|
113
|
+
if target.is_sequence_constructor and len(target.args) == 2:
|
|
114
|
+
iterator = sequence.args[0]
|
|
115
|
+
if iterator.is_name:
|
|
116
|
+
iterator_type = iterator.infer_type(iterator_scope)
|
|
117
|
+
if iterator_type.is_builtin_type:
|
|
118
|
+
# assume that builtin types have a length within Py_ssize_t
|
|
119
|
+
self.mark_assignment(
|
|
120
|
+
target.args[0],
|
|
121
|
+
ExprNodes.IntNode(target.pos, value='PY_SSIZE_T_MAX',
|
|
122
|
+
type=PyrexTypes.c_py_ssize_t_type))
|
|
123
|
+
target = target.args[1]
|
|
124
|
+
sequence = sequence.args[0]
|
|
125
|
+
if isinstance(sequence, ExprNodes.SimpleCallNode):
|
|
126
|
+
function = sequence.function
|
|
127
|
+
if sequence.self is None and function.is_name and function.name in ('range', 'xrange'):
|
|
128
|
+
entry = iterator_scope.lookup(function.name)
|
|
129
|
+
if not entry or entry.is_type and entry.type is Builtin.range_type:
|
|
130
|
+
is_special = True
|
|
131
|
+
for arg in sequence.args[:2]:
|
|
132
|
+
self.mark_assignment(target, arg)
|
|
133
|
+
if len(sequence.args) > 2:
|
|
134
|
+
self.mark_assignment(
|
|
135
|
+
target,
|
|
136
|
+
ExprNodes.binop_node(node.pos,
|
|
137
|
+
'+',
|
|
138
|
+
sequence.args[0],
|
|
139
|
+
sequence.args[2]))
|
|
140
|
+
if not is_special:
|
|
141
|
+
# A for-loop basically translates to subsequent calls to
|
|
142
|
+
# __getitem__(), so using an IndexNode here allows us to
|
|
143
|
+
# naturally infer the base type of pointers, C arrays,
|
|
144
|
+
# Python strings, etc., while correctly falling back to an
|
|
145
|
+
# object type when the base type cannot be handled.
|
|
146
|
+
self.mark_assignment(target, ExprNodes.IndexNode(
|
|
147
|
+
node.pos,
|
|
148
|
+
base=sequence,
|
|
149
|
+
index=ExprNodes.IntNode(target.pos, value='PY_SSIZE_T_MAX',
|
|
150
|
+
type=PyrexTypes.c_py_ssize_t_type)))
|
|
151
|
+
|
|
152
|
+
self.visitchildren(node)
|
|
153
|
+
return node
|
|
154
|
+
|
|
155
|
+
def visit_ForFromStatNode(self, node):
|
|
156
|
+
self.mark_assignment(node.target, node.bound1)
|
|
157
|
+
if node.step is not None:
|
|
158
|
+
self.mark_assignment(node.target,
|
|
159
|
+
ExprNodes.binop_node(node.pos,
|
|
160
|
+
'+',
|
|
161
|
+
node.bound1,
|
|
162
|
+
node.step))
|
|
163
|
+
self.visitchildren(node)
|
|
164
|
+
return node
|
|
165
|
+
|
|
166
|
+
def visit_WhileStatNode(self, node):
|
|
167
|
+
self.visitchildren(node)
|
|
168
|
+
return node
|
|
169
|
+
|
|
170
|
+
def visit_ExceptClauseNode(self, node):
|
|
171
|
+
if node.target is not None:
|
|
172
|
+
self.mark_assignment(node.target, node.exc_value)
|
|
173
|
+
self.visitchildren(node)
|
|
174
|
+
return node
|
|
175
|
+
|
|
176
|
+
def visit_FromCImportStatNode(self, node):
|
|
177
|
+
return node # Can't be assigned to...
|
|
178
|
+
|
|
179
|
+
def visit_FromImportStatNode(self, node):
|
|
180
|
+
for name, target in node.items:
|
|
181
|
+
if name != "*":
|
|
182
|
+
self.mark_assignment(target, object_expr)
|
|
183
|
+
self.visitchildren(node)
|
|
184
|
+
return node
|
|
185
|
+
|
|
186
|
+
def visit_DefNode(self, node):
|
|
187
|
+
# use fake expressions with the right result type
|
|
188
|
+
if node.star_arg:
|
|
189
|
+
self.mark_assignment(
|
|
190
|
+
node.star_arg, TypedExprNode(Builtin.tuple_type, node.pos))
|
|
191
|
+
if node.starstar_arg:
|
|
192
|
+
self.mark_assignment(
|
|
193
|
+
node.starstar_arg, TypedExprNode(Builtin.dict_type, node.pos))
|
|
194
|
+
EnvTransform.visit_FuncDefNode(self, node)
|
|
195
|
+
return node
|
|
196
|
+
|
|
197
|
+
def visit_DelStatNode(self, node):
|
|
198
|
+
for arg in node.args:
|
|
199
|
+
self.mark_assignment(arg, arg)
|
|
200
|
+
self.visitchildren(node)
|
|
201
|
+
return node
|
|
202
|
+
|
|
203
|
+
def visit_ParallelStatNode(self, node):
|
|
204
|
+
if self.parallel_block_stack:
|
|
205
|
+
node.parent = self.parallel_block_stack[-1]
|
|
206
|
+
else:
|
|
207
|
+
node.parent = None
|
|
208
|
+
|
|
209
|
+
nested = False
|
|
210
|
+
if node.is_prange:
|
|
211
|
+
if not node.parent:
|
|
212
|
+
node.is_parallel = True
|
|
213
|
+
else:
|
|
214
|
+
node.is_parallel = (node.parent.is_prange or not
|
|
215
|
+
node.parent.is_parallel)
|
|
216
|
+
nested = node.parent.is_prange
|
|
217
|
+
else:
|
|
218
|
+
node.is_parallel = True
|
|
219
|
+
# Note: nested with parallel() blocks are handled by
|
|
220
|
+
# ParallelRangeTransform!
|
|
221
|
+
# nested = node.parent
|
|
222
|
+
nested = node.parent and node.parent.is_prange
|
|
223
|
+
|
|
224
|
+
self.parallel_block_stack.append(node)
|
|
225
|
+
|
|
226
|
+
nested = nested or len(self.parallel_block_stack) > 2
|
|
227
|
+
if not self.parallel_errors and nested and not node.is_prange:
|
|
228
|
+
error(node.pos, "Only prange() may be nested")
|
|
229
|
+
self.parallel_errors = True
|
|
230
|
+
|
|
231
|
+
if node.is_prange:
|
|
232
|
+
self.visitchildren(node, attrs=('body', 'target', 'args'))
|
|
233
|
+
|
|
234
|
+
self.parallel_block_stack.pop()
|
|
235
|
+
if node.else_clause:
|
|
236
|
+
node.else_clause = self.visit(node.else_clause)
|
|
237
|
+
else:
|
|
238
|
+
self.visitchildren(node)
|
|
239
|
+
self.parallel_block_stack.pop()
|
|
240
|
+
|
|
241
|
+
self.parallel_errors = False
|
|
242
|
+
return node
|
|
243
|
+
|
|
244
|
+
def visit_YieldExprNode(self, node):
|
|
245
|
+
if self.parallel_block_stack:
|
|
246
|
+
error(node.pos, "'%s' not allowed in parallel sections" % node.expr_keyword)
|
|
247
|
+
return node
|
|
248
|
+
|
|
249
|
+
def visit_ReturnStatNode(self, node):
|
|
250
|
+
node.in_parallel = bool(self.parallel_block_stack)
|
|
251
|
+
return node
|
|
252
|
+
|
|
253
|
+
def visit_ExprNode(self, node):
|
|
254
|
+
self.visitchildren(node)
|
|
255
|
+
if self.parallel_block_stack:
|
|
256
|
+
node.in_parallel_block = True
|
|
257
|
+
return node
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class MarkOverflowingArithmetic(CythonTransform):
|
|
261
|
+
|
|
262
|
+
# It may be possible to integrate this with the above for
|
|
263
|
+
# performance improvements (though likely not worth it).
|
|
264
|
+
|
|
265
|
+
might_overflow = False
|
|
266
|
+
|
|
267
|
+
def __call__(self, root):
|
|
268
|
+
self.env_stack = []
|
|
269
|
+
self.env = root.scope
|
|
270
|
+
return super().__call__(root)
|
|
271
|
+
|
|
272
|
+
def visit_safe_node(self, node):
|
|
273
|
+
self.might_overflow, saved = False, self.might_overflow
|
|
274
|
+
self.visitchildren(node)
|
|
275
|
+
self.might_overflow = saved
|
|
276
|
+
return node
|
|
277
|
+
|
|
278
|
+
def visit_neutral_node(self, node):
|
|
279
|
+
self.visitchildren(node)
|
|
280
|
+
return node
|
|
281
|
+
|
|
282
|
+
def visit_dangerous_node(self, node):
|
|
283
|
+
self.might_overflow, saved = True, self.might_overflow
|
|
284
|
+
self.visitchildren(node)
|
|
285
|
+
self.might_overflow = saved
|
|
286
|
+
return node
|
|
287
|
+
|
|
288
|
+
def visit_FuncDefNode(self, node):
|
|
289
|
+
self.env_stack.append(self.env)
|
|
290
|
+
self.env = node.local_scope
|
|
291
|
+
self.visit_safe_node(node)
|
|
292
|
+
self.env = self.env_stack.pop()
|
|
293
|
+
return node
|
|
294
|
+
|
|
295
|
+
def visit_NameNode(self, node):
|
|
296
|
+
if self.might_overflow:
|
|
297
|
+
entry = node.entry or self.env.lookup(node.name)
|
|
298
|
+
if entry:
|
|
299
|
+
entry.might_overflow = True
|
|
300
|
+
return node
|
|
301
|
+
|
|
302
|
+
def visit_BinopNode(self, node):
|
|
303
|
+
if node.operator in '&|^':
|
|
304
|
+
return self.visit_neutral_node(node)
|
|
305
|
+
else:
|
|
306
|
+
return self.visit_dangerous_node(node)
|
|
307
|
+
|
|
308
|
+
def visit_SimpleCallNode(self, node):
|
|
309
|
+
if node.function.is_name and node.function.name == 'abs':
|
|
310
|
+
# Overflows for minimum value of fixed size ints.
|
|
311
|
+
return self.visit_dangerous_node(node)
|
|
312
|
+
else:
|
|
313
|
+
return self.visit_neutral_node(node)
|
|
314
|
+
|
|
315
|
+
visit_UnopNode = visit_neutral_node
|
|
316
|
+
|
|
317
|
+
visit_UnaryMinusNode = visit_dangerous_node
|
|
318
|
+
|
|
319
|
+
visit_InPlaceAssignmentNode = visit_dangerous_node
|
|
320
|
+
|
|
321
|
+
visit_Node = visit_safe_node
|
|
322
|
+
|
|
323
|
+
def visit_assignment(self, lhs, rhs):
|
|
324
|
+
if (isinstance(rhs, ExprNodes.IntNode)
|
|
325
|
+
and isinstance(lhs, ExprNodes.NameNode)
|
|
326
|
+
and Utils.long_literal(rhs.value)):
|
|
327
|
+
entry = lhs.entry or self.env.lookup(lhs.name)
|
|
328
|
+
if entry:
|
|
329
|
+
entry.might_overflow = True
|
|
330
|
+
|
|
331
|
+
def visit_SingleAssignmentNode(self, node):
|
|
332
|
+
self.visit_assignment(node.lhs, node.rhs)
|
|
333
|
+
self.visitchildren(node)
|
|
334
|
+
return node
|
|
335
|
+
|
|
336
|
+
def visit_CascadedAssignmentNode(self, node):
|
|
337
|
+
for lhs in node.lhs_list:
|
|
338
|
+
self.visit_assignment(lhs, node.rhs)
|
|
339
|
+
self.visitchildren(node)
|
|
340
|
+
return node
|
|
341
|
+
|
|
342
|
+
class PyObjectTypeInferer:
|
|
343
|
+
"""
|
|
344
|
+
If it's not declared, it's a PyObject.
|
|
345
|
+
"""
|
|
346
|
+
def infer_types(self, scope):
|
|
347
|
+
"""
|
|
348
|
+
Given a dict of entries, map all unspecified types to a specified type.
|
|
349
|
+
"""
|
|
350
|
+
for name, entry in scope.entries.items():
|
|
351
|
+
if entry.type is unspecified_type:
|
|
352
|
+
entry.type = py_object_type
|
|
353
|
+
|
|
354
|
+
class SimpleAssignmentTypeInferer:
|
|
355
|
+
"""
|
|
356
|
+
Very basic type inference.
|
|
357
|
+
|
|
358
|
+
Note: in order to support cross-closure type inference, this must be
|
|
359
|
+
applies to nested scopes in top-down order.
|
|
360
|
+
"""
|
|
361
|
+
def set_entry_type(self, entry, entry_type, scope):
|
|
362
|
+
for e in entry.all_entries():
|
|
363
|
+
e.type = entry_type
|
|
364
|
+
if e.type.is_memoryviewslice:
|
|
365
|
+
# memoryview slices crash if they don't get initialized
|
|
366
|
+
e.init = e.type.default_value
|
|
367
|
+
if e.type.is_cpp_class:
|
|
368
|
+
if scope.directives['cpp_locals']:
|
|
369
|
+
e.make_cpp_optional()
|
|
370
|
+
else:
|
|
371
|
+
e.type.check_nullary_constructor(entry.pos)
|
|
372
|
+
|
|
373
|
+
def infer_types(self, scope):
|
|
374
|
+
enabled = scope.directives['infer_types']
|
|
375
|
+
verbose = scope.directives['infer_types.verbose']
|
|
376
|
+
|
|
377
|
+
if enabled == True:
|
|
378
|
+
spanning_type = aggressive_spanning_type
|
|
379
|
+
elif enabled is None: # safe mode
|
|
380
|
+
spanning_type = safe_spanning_type
|
|
381
|
+
else:
|
|
382
|
+
for entry in scope.entries.values():
|
|
383
|
+
if entry.type is unspecified_type:
|
|
384
|
+
self.set_entry_type(entry, py_object_type, scope)
|
|
385
|
+
return
|
|
386
|
+
|
|
387
|
+
# Set of assignments
|
|
388
|
+
assignments = set()
|
|
389
|
+
assmts_resolved = set()
|
|
390
|
+
dependencies = {}
|
|
391
|
+
assmt_to_names = {}
|
|
392
|
+
|
|
393
|
+
for name, entry in scope.entries.items():
|
|
394
|
+
for assmt in entry.cf_assignments:
|
|
395
|
+
names = assmt.type_dependencies()
|
|
396
|
+
assmt_to_names[assmt] = names
|
|
397
|
+
assmts = set()
|
|
398
|
+
for node in names:
|
|
399
|
+
assmts.update(node.cf_state)
|
|
400
|
+
dependencies[assmt] = assmts
|
|
401
|
+
if entry.type is unspecified_type:
|
|
402
|
+
assignments.update(entry.cf_assignments)
|
|
403
|
+
else:
|
|
404
|
+
assmts_resolved.update(entry.cf_assignments)
|
|
405
|
+
|
|
406
|
+
def infer_name_node_type(node):
|
|
407
|
+
types = [assmt.inferred_type for assmt in node.cf_state]
|
|
408
|
+
if not types:
|
|
409
|
+
node_type = py_object_type
|
|
410
|
+
else:
|
|
411
|
+
entry = node.entry
|
|
412
|
+
node_type = spanning_type(
|
|
413
|
+
types, entry.might_overflow, scope)
|
|
414
|
+
node.inferred_type = node_type
|
|
415
|
+
|
|
416
|
+
def infer_name_node_type_partial(node):
|
|
417
|
+
types = [assmt.inferred_type for assmt in node.cf_state
|
|
418
|
+
if assmt.inferred_type is not None]
|
|
419
|
+
if not types:
|
|
420
|
+
return
|
|
421
|
+
entry = node.entry
|
|
422
|
+
return spanning_type(types, entry.might_overflow, scope)
|
|
423
|
+
|
|
424
|
+
def inferred_types(entry):
|
|
425
|
+
has_none = False
|
|
426
|
+
has_pyobjects = False
|
|
427
|
+
types = []
|
|
428
|
+
for assmt in entry.cf_assignments:
|
|
429
|
+
if assmt.rhs.is_none:
|
|
430
|
+
has_none = True
|
|
431
|
+
else:
|
|
432
|
+
rhs_type = assmt.inferred_type
|
|
433
|
+
if rhs_type and rhs_type.is_pyobject:
|
|
434
|
+
has_pyobjects = True
|
|
435
|
+
types.append(rhs_type)
|
|
436
|
+
# Ignore None assignments as long as there are concrete Python type assignments.
|
|
437
|
+
# but include them if None is the only assigned Python object.
|
|
438
|
+
if has_none and not has_pyobjects:
|
|
439
|
+
types.append(py_object_type)
|
|
440
|
+
return types
|
|
441
|
+
|
|
442
|
+
def resolve_assignments(assignments):
|
|
443
|
+
resolved = set()
|
|
444
|
+
for assmt in assignments:
|
|
445
|
+
deps = dependencies[assmt]
|
|
446
|
+
# All assignments are resolved
|
|
447
|
+
if assmts_resolved.issuperset(deps):
|
|
448
|
+
for node in assmt_to_names[assmt]:
|
|
449
|
+
infer_name_node_type(node)
|
|
450
|
+
# Resolve assmt
|
|
451
|
+
inferred_type = assmt.infer_type()
|
|
452
|
+
assmts_resolved.add(assmt)
|
|
453
|
+
resolved.add(assmt)
|
|
454
|
+
assignments.difference_update(resolved)
|
|
455
|
+
return resolved
|
|
456
|
+
|
|
457
|
+
def partial_infer(assmt):
|
|
458
|
+
partial_types = []
|
|
459
|
+
for node in assmt_to_names[assmt]:
|
|
460
|
+
partial_type = infer_name_node_type_partial(node)
|
|
461
|
+
if partial_type is None:
|
|
462
|
+
return False
|
|
463
|
+
partial_types.append((node, partial_type))
|
|
464
|
+
for node, partial_type in partial_types:
|
|
465
|
+
node.inferred_type = partial_type
|
|
466
|
+
assmt.infer_type()
|
|
467
|
+
return True
|
|
468
|
+
|
|
469
|
+
partial_assmts = set()
|
|
470
|
+
def resolve_partial(assignments):
|
|
471
|
+
# try to handle circular references
|
|
472
|
+
partials = set()
|
|
473
|
+
for assmt in assignments:
|
|
474
|
+
if assmt in partial_assmts:
|
|
475
|
+
continue
|
|
476
|
+
if partial_infer(assmt):
|
|
477
|
+
partials.add(assmt)
|
|
478
|
+
assmts_resolved.add(assmt)
|
|
479
|
+
partial_assmts.update(partials)
|
|
480
|
+
return partials
|
|
481
|
+
|
|
482
|
+
# Infer assignments
|
|
483
|
+
while True:
|
|
484
|
+
if not resolve_assignments(assignments):
|
|
485
|
+
if not resolve_partial(assignments):
|
|
486
|
+
break
|
|
487
|
+
inferred = set()
|
|
488
|
+
# First pass
|
|
489
|
+
for entry in scope.entries.values():
|
|
490
|
+
if entry.type is not unspecified_type:
|
|
491
|
+
continue
|
|
492
|
+
entry_type = py_object_type
|
|
493
|
+
if assmts_resolved.issuperset(entry.cf_assignments):
|
|
494
|
+
types = inferred_types(entry)
|
|
495
|
+
if types and all(types):
|
|
496
|
+
entry_type = spanning_type(
|
|
497
|
+
types, entry.might_overflow, scope)
|
|
498
|
+
inferred.add(entry)
|
|
499
|
+
self.set_entry_type(entry, entry_type, scope)
|
|
500
|
+
|
|
501
|
+
def reinfer():
|
|
502
|
+
dirty = False
|
|
503
|
+
for entry in inferred:
|
|
504
|
+
for assmt in entry.cf_assignments:
|
|
505
|
+
assmt.infer_type()
|
|
506
|
+
types = inferred_types(entry)
|
|
507
|
+
new_type = spanning_type(types, entry.might_overflow, scope)
|
|
508
|
+
if new_type != entry.type:
|
|
509
|
+
self.set_entry_type(entry, new_type, scope)
|
|
510
|
+
dirty = True
|
|
511
|
+
return dirty
|
|
512
|
+
|
|
513
|
+
# types propagation
|
|
514
|
+
while reinfer():
|
|
515
|
+
pass
|
|
516
|
+
|
|
517
|
+
if verbose:
|
|
518
|
+
for entry in inferred:
|
|
519
|
+
message(entry.pos, "inferred '%s' to be of type '%s'" % (
|
|
520
|
+
entry.name, entry.type))
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def find_spanning_type(type1, type2):
|
|
524
|
+
if type1 is type2:
|
|
525
|
+
result_type = type1
|
|
526
|
+
elif type1 is PyrexTypes.c_bint_type or type2 is PyrexTypes.c_bint_type:
|
|
527
|
+
# type inference can break the coercion back to a Python bool
|
|
528
|
+
# if it returns an arbitrary int type here
|
|
529
|
+
return py_object_type
|
|
530
|
+
else:
|
|
531
|
+
result_type = PyrexTypes.spanning_type(type1, type2)
|
|
532
|
+
if result_type in (PyrexTypes.c_double_type, PyrexTypes.c_float_type,
|
|
533
|
+
Builtin.float_type):
|
|
534
|
+
# Python's float type is just a C double, so it's safe to
|
|
535
|
+
# use the C type instead
|
|
536
|
+
return PyrexTypes.c_double_type
|
|
537
|
+
return result_type
|
|
538
|
+
|
|
539
|
+
def simply_type(result_type):
|
|
540
|
+
result_type = PyrexTypes.remove_cv_ref(result_type, remove_fakeref=True)
|
|
541
|
+
if result_type.is_array:
|
|
542
|
+
result_type = PyrexTypes.c_ptr_type(result_type.base_type)
|
|
543
|
+
return result_type
|
|
544
|
+
|
|
545
|
+
def aggressive_spanning_type(types, might_overflow, scope):
|
|
546
|
+
return simply_type(reduce(find_spanning_type, types))
|
|
547
|
+
|
|
548
|
+
def safe_spanning_type(types, might_overflow, scope):
|
|
549
|
+
result_type = simply_type(reduce(find_spanning_type, types))
|
|
550
|
+
if result_type.is_pyobject:
|
|
551
|
+
return result_type
|
|
552
|
+
elif (result_type is PyrexTypes.c_double_type or
|
|
553
|
+
result_type is PyrexTypes.c_float_type):
|
|
554
|
+
# Python's float type is just a C double, so it's safe to use
|
|
555
|
+
# the C type instead. Similarly if given a C float, it leads to
|
|
556
|
+
# a small loss of precision vs Python but is otherwise the same
|
|
557
|
+
return result_type
|
|
558
|
+
elif result_type is PyrexTypes.c_bint_type:
|
|
559
|
+
# find_spanning_type() only returns 'bint' for clean boolean
|
|
560
|
+
# operations without other int types, so this is safe, too
|
|
561
|
+
return result_type
|
|
562
|
+
elif result_type.is_pythran_expr:
|
|
563
|
+
return result_type
|
|
564
|
+
elif result_type.is_ptr:
|
|
565
|
+
# Any pointer except (signed|unsigned|) char* can't implicitly
|
|
566
|
+
# become a PyObject, and inferring char* is now accepted, too.
|
|
567
|
+
return result_type
|
|
568
|
+
elif result_type.is_cpp_class:
|
|
569
|
+
# These can't implicitly become Python objects either.
|
|
570
|
+
return result_type
|
|
571
|
+
elif result_type.is_struct:
|
|
572
|
+
# Though we have struct -> object for some structs, this is uncommonly
|
|
573
|
+
# used, won't arise in pure Python, and there shouldn't be side
|
|
574
|
+
# effects, so I'm declaring this safe.
|
|
575
|
+
return result_type
|
|
576
|
+
elif result_type.is_memoryviewslice:
|
|
577
|
+
return result_type
|
|
578
|
+
elif result_type is PyrexTypes.soft_complex_type:
|
|
579
|
+
return result_type
|
|
580
|
+
elif result_type == PyrexTypes.c_double_complex_type:
|
|
581
|
+
return result_type
|
|
582
|
+
elif (result_type.is_int or result_type.is_enum) and not might_overflow:
|
|
583
|
+
return result_type
|
|
584
|
+
elif (not result_type.can_coerce_to_pyobject(scope)
|
|
585
|
+
and not result_type.is_error):
|
|
586
|
+
return result_type
|
|
587
|
+
return py_object_type
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def get_type_inferer():
|
|
591
|
+
return SimpleAssignmentTypeInferer()
|