Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +2 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Build/Tests/__pycache__/TestCyCache.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Build/Tests/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Annotate.py +341 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Code.cpython-311-x86_64-linux-gnu.so +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/CythonScope.py +181 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/ExprNodes.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FlowControl.pxd +111 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FlowControl.py +1383 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Main.py +789 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Naming.py +198 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Optimize.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/ParseTreeTransforms.pxd +84 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Parsing.cpython-311-x86_64-linux-gnu.so +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Parsing.pxd +205 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Pipeline.py +419 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Scanning.pxd +63 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/TestGrammar.py +203 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/TreePath.py +296 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/TypeSlots.py +1180 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/UFuncs.py +286 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/UtilNodes.py +388 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Visitor.py +871 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/CmdLine.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/CodeGeneration.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/DebugFlags.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/FlowControl.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/Interpreter.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/StringEncoding.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/TypeSlots.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tests/__init__.py +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tests/__pycache__/TestJediTyper.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst +28 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/METADATA +93 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL +6 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/INSTALLER +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/RECORD +23 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/top_level.txt +1 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/__pycache__/utils.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__init__.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__pycache__/meta.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/ATen/templates/DispatchKeyNativeFunctions.cpp +13 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/README.md +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/__pycache__/gen_annotated_fn_args.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/__pycache__/gen_view_funcs.cpython-311.pyc +0 -0
.gitattributes
CHANGED
|
@@ -39,3 +39,5 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/_
|
|
| 39 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/Scanners.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 40 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/DFA.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 41 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FusedNode.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 39 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/Scanners.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 40 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Plex/DFA.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 41 |
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FusedNode.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Code.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Parsing.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Build/Tests/__pycache__/TestCyCache.cpython-311.pyc
ADDED
|
Binary file (10.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Build/Tests/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (219 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Annotate.py
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Note: Work in progress
|
| 2 |
+
|
| 3 |
+
from __future__ import absolute_import
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
import os.path
|
| 7 |
+
import re
|
| 8 |
+
import codecs
|
| 9 |
+
import textwrap
|
| 10 |
+
from datetime import datetime
|
| 11 |
+
from functools import partial
|
| 12 |
+
from collections import defaultdict
|
| 13 |
+
from xml.sax.saxutils import escape as html_escape
|
| 14 |
+
try:
|
| 15 |
+
from StringIO import StringIO
|
| 16 |
+
except ImportError:
|
| 17 |
+
from io import StringIO # does not support writing 'str' in Py2
|
| 18 |
+
|
| 19 |
+
from . import Version
|
| 20 |
+
from .Code import CCodeWriter
|
| 21 |
+
from .. import Utils
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class AnnotationCCodeWriter(CCodeWriter):
|
| 25 |
+
|
| 26 |
+
# also used as marker for detection of complete code emission in tests
|
| 27 |
+
COMPLETE_CODE_TITLE = "Complete cythonized code"
|
| 28 |
+
|
| 29 |
+
def __init__(self, create_from=None, buffer=None, copy_formatting=True, show_entire_c_code=False, source_desc=None):
|
| 30 |
+
CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting)
|
| 31 |
+
self.show_entire_c_code = show_entire_c_code
|
| 32 |
+
if create_from is None:
|
| 33 |
+
self.annotation_buffer = StringIO()
|
| 34 |
+
self.last_annotated_pos = None
|
| 35 |
+
# annotations[filename][line] -> [(column, AnnotationItem)*]
|
| 36 |
+
self.annotations = defaultdict(partial(defaultdict, list))
|
| 37 |
+
# code[filename][line] -> str
|
| 38 |
+
self.code = defaultdict(partial(defaultdict, str))
|
| 39 |
+
# scopes[filename][line] -> set(scopes)
|
| 40 |
+
self.scopes = defaultdict(partial(defaultdict, set))
|
| 41 |
+
else:
|
| 42 |
+
# When creating an insertion point, keep references to the same database
|
| 43 |
+
self.annotation_buffer = create_from.annotation_buffer
|
| 44 |
+
self.annotations = create_from.annotations
|
| 45 |
+
self.code = create_from.code
|
| 46 |
+
self.scopes = create_from.scopes
|
| 47 |
+
self.last_annotated_pos = create_from.last_annotated_pos
|
| 48 |
+
|
| 49 |
+
def create_new(self, create_from, buffer, copy_formatting):
|
| 50 |
+
return AnnotationCCodeWriter(create_from, buffer, copy_formatting)
|
| 51 |
+
|
| 52 |
+
def _write_to_buffer(self, s):
|
| 53 |
+
self.buffer.write(s)
|
| 54 |
+
self.annotation_buffer.write(s)
|
| 55 |
+
|
| 56 |
+
def mark_pos(self, pos, trace=True):
|
| 57 |
+
if pos is not None:
|
| 58 |
+
CCodeWriter.mark_pos(self, pos, trace)
|
| 59 |
+
if self.funcstate and self.funcstate.scope:
|
| 60 |
+
# lambdas and genexprs can result in multiple scopes per line => keep them in a set
|
| 61 |
+
self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope)
|
| 62 |
+
if self.last_annotated_pos:
|
| 63 |
+
source_desc, line, _ = self.last_annotated_pos
|
| 64 |
+
pos_code = self.code[source_desc.filename]
|
| 65 |
+
pos_code[line] += self.annotation_buffer.getvalue()
|
| 66 |
+
self.annotation_buffer = StringIO()
|
| 67 |
+
self.last_annotated_pos = pos
|
| 68 |
+
|
| 69 |
+
def annotate(self, pos, item):
|
| 70 |
+
self.annotations[pos[0].filename][pos[1]].append((pos[2], item))
|
| 71 |
+
|
| 72 |
+
def _css(self):
|
| 73 |
+
"""css template will later allow to choose a colormap"""
|
| 74 |
+
css = [self._css_template]
|
| 75 |
+
for i in range(255):
|
| 76 |
+
color = u"FFFF%02x" % int(255.0 // (1.0 + i/10.0))
|
| 77 |
+
css.append('.cython.score-%d {background-color: #%s;}' % (i, color))
|
| 78 |
+
try:
|
| 79 |
+
from pygments.formatters import HtmlFormatter
|
| 80 |
+
except ImportError:
|
| 81 |
+
pass
|
| 82 |
+
else:
|
| 83 |
+
css.append(HtmlFormatter().get_style_defs('.cython'))
|
| 84 |
+
return '\n'.join(css)
|
| 85 |
+
|
| 86 |
+
_css_template = textwrap.dedent("""
|
| 87 |
+
body.cython { font-family: courier; font-size: 12; }
|
| 88 |
+
|
| 89 |
+
.cython.tag { }
|
| 90 |
+
.cython.line { color: #000000; margin: 0em }
|
| 91 |
+
.cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }
|
| 92 |
+
|
| 93 |
+
.cython.line .run { background-color: #B0FFB0; }
|
| 94 |
+
.cython.line .mis { background-color: #FFB0B0; }
|
| 95 |
+
.cython.code.run { border-left: 8px solid #B0FFB0; }
|
| 96 |
+
.cython.code.mis { border-left: 8px solid #FFB0B0; }
|
| 97 |
+
|
| 98 |
+
.cython.code .py_c_api { color: red; }
|
| 99 |
+
.cython.code .py_macro_api { color: #FF7000; }
|
| 100 |
+
.cython.code .pyx_c_api { color: #FF3000; }
|
| 101 |
+
.cython.code .pyx_macro_api { color: #FF7000; }
|
| 102 |
+
.cython.code .refnanny { color: #FFA000; }
|
| 103 |
+
.cython.code .trace { color: #FFA000; }
|
| 104 |
+
.cython.code .error_goto { color: #FFA000; }
|
| 105 |
+
|
| 106 |
+
.cython.code .coerce { color: #008000; border: 1px dotted #008000 }
|
| 107 |
+
.cython.code .py_attr { color: #FF0000; font-weight: bold; }
|
| 108 |
+
.cython.code .c_attr { color: #0000FF; }
|
| 109 |
+
.cython.code .py_call { color: #FF0000; font-weight: bold; }
|
| 110 |
+
.cython.code .c_call { color: #0000FF; }
|
| 111 |
+
""")
|
| 112 |
+
|
| 113 |
+
# on-click toggle function to show/hide C source code
|
| 114 |
+
_onclick_attr = ' onclick="{0}"'.format((
|
| 115 |
+
"(function(s){"
|
| 116 |
+
" s.display = s.display === 'block' ? 'none' : 'block'"
|
| 117 |
+
"})(this.nextElementSibling.style)"
|
| 118 |
+
).replace(' ', '') # poor dev's JS minification
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
def save_annotation(self, source_filename, target_filename, coverage_xml=None):
|
| 122 |
+
with Utils.open_source_file(source_filename) as f:
|
| 123 |
+
code = f.read()
|
| 124 |
+
generated_code = self.code.get(source_filename, {})
|
| 125 |
+
c_file = Utils.decode_filename(os.path.basename(target_filename))
|
| 126 |
+
html_filename = os.path.splitext(target_filename)[0] + ".html"
|
| 127 |
+
|
| 128 |
+
with codecs.open(html_filename, "w", encoding="UTF-8") as out_buffer:
|
| 129 |
+
out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml))
|
| 130 |
+
|
| 131 |
+
def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None):
|
| 132 |
+
coverage_info = ''
|
| 133 |
+
if coverage_timestamp:
|
| 134 |
+
coverage_info = u' with coverage data from {timestamp}'.format(
|
| 135 |
+
timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000))
|
| 136 |
+
|
| 137 |
+
outlist = [
|
| 138 |
+
textwrap.dedent(u'''\
|
| 139 |
+
<!DOCTYPE html>
|
| 140 |
+
<!-- Generated by Cython {watermark} -->
|
| 141 |
+
<html>
|
| 142 |
+
<head>
|
| 143 |
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
| 144 |
+
<title>Cython: {filename}</title>
|
| 145 |
+
<style type="text/css">
|
| 146 |
+
{css}
|
| 147 |
+
</style>
|
| 148 |
+
</head>
|
| 149 |
+
<body class="cython">
|
| 150 |
+
<p><span style="border-bottom: solid 1px grey;">Generated by Cython {watermark}</span>{more_info}</p>
|
| 151 |
+
<p>
|
| 152 |
+
<span style="background-color: #FFFF00">Yellow lines</span> hint at Python interaction.<br />
|
| 153 |
+
Click on a line that starts with a "<code>+</code>" to see the C code that Cython generated for it.
|
| 154 |
+
</p>
|
| 155 |
+
''').format(css=self._css(), watermark=Version.watermark,
|
| 156 |
+
filename=os.path.basename(source_filename) if source_filename else '',
|
| 157 |
+
more_info=coverage_info)
|
| 158 |
+
]
|
| 159 |
+
if c_file:
|
| 160 |
+
outlist.append(u'<p>Raw output: <a href="%s">%s</a></p>\n' % (c_file, c_file))
|
| 161 |
+
return outlist
|
| 162 |
+
|
| 163 |
+
def _save_annotation_footer(self):
|
| 164 |
+
return (u'</body></html>\n',)
|
| 165 |
+
|
| 166 |
+
def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None):
|
| 167 |
+
"""
|
| 168 |
+
lines : original cython source code split by lines
|
| 169 |
+
generated_code : generated c code keyed by line number in original file
|
| 170 |
+
target filename : name of the file in which to store the generated html
|
| 171 |
+
c_file : filename in which the c_code has been written
|
| 172 |
+
"""
|
| 173 |
+
if coverage_xml is not None and source_filename:
|
| 174 |
+
coverage_timestamp = coverage_xml.get('timestamp', '').strip()
|
| 175 |
+
covered_lines = self._get_line_coverage(coverage_xml, source_filename)
|
| 176 |
+
else:
|
| 177 |
+
coverage_timestamp = covered_lines = None
|
| 178 |
+
annotation_items = dict(self.annotations[source_filename])
|
| 179 |
+
scopes = dict(self.scopes[source_filename])
|
| 180 |
+
|
| 181 |
+
outlist = []
|
| 182 |
+
outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp))
|
| 183 |
+
outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines))
|
| 184 |
+
outlist.extend(self._save_annotation_footer())
|
| 185 |
+
return ''.join(outlist)
|
| 186 |
+
|
| 187 |
+
def _get_line_coverage(self, coverage_xml, source_filename):
|
| 188 |
+
coverage_data = None
|
| 189 |
+
for entry in coverage_xml.iterfind('.//class'):
|
| 190 |
+
if not entry.get('filename'):
|
| 191 |
+
continue
|
| 192 |
+
if (entry.get('filename') == source_filename or
|
| 193 |
+
os.path.abspath(entry.get('filename')) == source_filename):
|
| 194 |
+
coverage_data = entry
|
| 195 |
+
break
|
| 196 |
+
elif source_filename.endswith(entry.get('filename')):
|
| 197 |
+
coverage_data = entry # but we might still find a better match...
|
| 198 |
+
if coverage_data is None:
|
| 199 |
+
return None
|
| 200 |
+
return dict(
|
| 201 |
+
(int(line.get('number')), int(line.get('hits')))
|
| 202 |
+
for line in coverage_data.iterfind('lines/line')
|
| 203 |
+
)
|
| 204 |
+
|
| 205 |
+
def _htmlify_code(self, code, language):
|
| 206 |
+
try:
|
| 207 |
+
from pygments import highlight
|
| 208 |
+
from pygments.lexers import CythonLexer, CppLexer
|
| 209 |
+
from pygments.formatters import HtmlFormatter
|
| 210 |
+
except ImportError:
|
| 211 |
+
# no Pygments, just escape the code
|
| 212 |
+
return html_escape(code)
|
| 213 |
+
|
| 214 |
+
if language == "cython":
|
| 215 |
+
lexer = CythonLexer(stripnl=False, stripall=False)
|
| 216 |
+
elif language == "c/cpp":
|
| 217 |
+
lexer = CppLexer(stripnl=False, stripall=False)
|
| 218 |
+
else:
|
| 219 |
+
# unknown language, use fallback
|
| 220 |
+
return html_escape(code)
|
| 221 |
+
html_code = highlight(
|
| 222 |
+
code, lexer,
|
| 223 |
+
HtmlFormatter(nowrap=True))
|
| 224 |
+
return html_code
|
| 225 |
+
|
| 226 |
+
def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None):
|
| 227 |
+
outlist = [u'<div class="cython">']
|
| 228 |
+
pos_comment_marker = u'/* \N{HORIZONTAL ELLIPSIS} */\n'
|
| 229 |
+
new_calls_map = dict(
|
| 230 |
+
(name, 0) for name in
|
| 231 |
+
'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split()
|
| 232 |
+
).copy
|
| 233 |
+
|
| 234 |
+
self.mark_pos(None)
|
| 235 |
+
|
| 236 |
+
def annotate(match):
|
| 237 |
+
group_name = match.lastgroup
|
| 238 |
+
calls[group_name] += 1
|
| 239 |
+
return u"<span class='%s'>%s</span>" % (
|
| 240 |
+
group_name, match.group(group_name))
|
| 241 |
+
|
| 242 |
+
lines = self._htmlify_code(cython_code, "cython").splitlines()
|
| 243 |
+
lineno_width = len(str(len(lines)))
|
| 244 |
+
if not covered_lines:
|
| 245 |
+
covered_lines = None
|
| 246 |
+
|
| 247 |
+
for k, line in enumerate(lines, 1):
|
| 248 |
+
try:
|
| 249 |
+
c_code = generated_code[k]
|
| 250 |
+
except KeyError:
|
| 251 |
+
c_code = ''
|
| 252 |
+
else:
|
| 253 |
+
c_code = _replace_pos_comment(pos_comment_marker, c_code)
|
| 254 |
+
if c_code.startswith(pos_comment_marker):
|
| 255 |
+
c_code = c_code[len(pos_comment_marker):]
|
| 256 |
+
c_code = html_escape(c_code)
|
| 257 |
+
|
| 258 |
+
calls = new_calls_map()
|
| 259 |
+
c_code = _parse_code(annotate, c_code)
|
| 260 |
+
score = (5 * calls['py_c_api'] + 2 * calls['pyx_c_api'] +
|
| 261 |
+
calls['py_macro_api'] + calls['pyx_macro_api'])
|
| 262 |
+
|
| 263 |
+
if c_code:
|
| 264 |
+
onclick = self._onclick_attr
|
| 265 |
+
expandsymbol = '+'
|
| 266 |
+
else:
|
| 267 |
+
onclick = ''
|
| 268 |
+
expandsymbol = ' '
|
| 269 |
+
|
| 270 |
+
covered = ''
|
| 271 |
+
if covered_lines is not None and k in covered_lines:
|
| 272 |
+
hits = covered_lines[k]
|
| 273 |
+
if hits is not None:
|
| 274 |
+
covered = 'run' if hits else 'mis'
|
| 275 |
+
|
| 276 |
+
outlist.append(
|
| 277 |
+
u'<pre class="cython line score-{score}"{onclick}>'
|
| 278 |
+
# generate line number with expand symbol in front,
|
| 279 |
+
# and the right number of digit
|
| 280 |
+
u'{expandsymbol}<span class="{covered}">{line:0{lineno_width}d}</span>: {code}</pre>\n'.format(
|
| 281 |
+
score=score,
|
| 282 |
+
expandsymbol=expandsymbol,
|
| 283 |
+
covered=covered,
|
| 284 |
+
lineno_width=lineno_width,
|
| 285 |
+
line=k,
|
| 286 |
+
code=line.rstrip(),
|
| 287 |
+
onclick=onclick,
|
| 288 |
+
))
|
| 289 |
+
if c_code:
|
| 290 |
+
outlist.append(u"<pre class='cython code score-{score} {covered}'>{code}</pre>".format(
|
| 291 |
+
score=score, covered=covered, code=c_code))
|
| 292 |
+
outlist.append(u"</div>")
|
| 293 |
+
|
| 294 |
+
# now the whole c-code if needed:
|
| 295 |
+
if self.show_entire_c_code:
|
| 296 |
+
outlist.append(u'<p><div class="cython">')
|
| 297 |
+
onclick_title = u"<pre class='cython line'{onclick}>+ {title}</pre>\n"
|
| 298 |
+
outlist.append(onclick_title.format(
|
| 299 |
+
onclick=self._onclick_attr,
|
| 300 |
+
title=AnnotationCCodeWriter.COMPLETE_CODE_TITLE,
|
| 301 |
+
))
|
| 302 |
+
complete_code_as_html = self._htmlify_code(self.buffer.getvalue(), "c/cpp")
|
| 303 |
+
outlist.append(u"<pre class='cython code'>{code}</pre>".format(code=complete_code_as_html))
|
| 304 |
+
outlist.append(u"</div></p>")
|
| 305 |
+
|
| 306 |
+
return outlist
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
_parse_code = re.compile((
|
| 310 |
+
br'(?P<refnanny>__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|'
|
| 311 |
+
br'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
|
| 312 |
+
br'(?:'
|
| 313 |
+
br'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
|
| 314 |
+
br'(?P<pyx_c_api>(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|'
|
| 315 |
+
br'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
|
| 316 |
+
br'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
|
| 317 |
+
br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement
|
| 318 |
+
br'(?P<error_goto>(?:(?<=;) *if [^;]* +)?__PYX_ERR\([^)]+\))'
|
| 319 |
+
).decode('ascii')).sub
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
_replace_pos_comment = re.compile(
|
| 323 |
+
# this matches what Cython generates as code line marker comment
|
| 324 |
+
br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'),
|
| 325 |
+
re.M
|
| 326 |
+
).sub
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
class AnnotationItem(object):
|
| 330 |
+
|
| 331 |
+
def __init__(self, style, text, tag="", size=0):
|
| 332 |
+
self.style = style
|
| 333 |
+
self.text = text
|
| 334 |
+
self.tag = tag
|
| 335 |
+
self.size = size
|
| 336 |
+
|
| 337 |
+
def start(self):
|
| 338 |
+
return u"<span class='cython tag %s' title='%s'>%s" % (self.style, self.text, self.tag)
|
| 339 |
+
|
| 340 |
+
def end(self):
|
| 341 |
+
return self.size, u"</span>"
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Code.cpython-311-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4d946103cb5b89bdb2437bafe9bad2325d62a443935f3674d31ca3c7f1152a39
|
| 3 |
+
size 1342888
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/CythonScope.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
from .Symtab import ModuleScope
|
| 4 |
+
from .PyrexTypes import *
|
| 5 |
+
from .UtilityCode import CythonUtilityCode
|
| 6 |
+
from .Errors import error
|
| 7 |
+
from .Scanning import StringSourceDescriptor
|
| 8 |
+
from . import MemoryView
|
| 9 |
+
from .StringEncoding import EncodedString
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class CythonScope(ModuleScope):
|
| 13 |
+
is_cython_builtin = 1
|
| 14 |
+
_cythonscope_initialized = False
|
| 15 |
+
|
| 16 |
+
def __init__(self, context):
|
| 17 |
+
ModuleScope.__init__(self, u'cython', None, None)
|
| 18 |
+
self.pxd_file_loaded = True
|
| 19 |
+
self.populate_cython_scope()
|
| 20 |
+
# The Main.Context object
|
| 21 |
+
self.context = context
|
| 22 |
+
|
| 23 |
+
for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type):
|
| 24 |
+
entry = self.declare_typedef(fused_type.name,
|
| 25 |
+
fused_type,
|
| 26 |
+
None,
|
| 27 |
+
cname='<error>')
|
| 28 |
+
entry.in_cinclude = True
|
| 29 |
+
|
| 30 |
+
def is_cpp(self):
|
| 31 |
+
# Allow C++ utility code in C++ contexts.
|
| 32 |
+
return self.context.cpp
|
| 33 |
+
|
| 34 |
+
def lookup_type(self, name):
|
| 35 |
+
# This function should go away when types are all first-level objects.
|
| 36 |
+
type = parse_basic_type(name)
|
| 37 |
+
if type:
|
| 38 |
+
return type
|
| 39 |
+
|
| 40 |
+
return super(CythonScope, self).lookup_type(name)
|
| 41 |
+
|
| 42 |
+
def lookup(self, name):
|
| 43 |
+
entry = super(CythonScope, self).lookup(name)
|
| 44 |
+
|
| 45 |
+
if entry is None and not self._cythonscope_initialized:
|
| 46 |
+
self.load_cythonscope()
|
| 47 |
+
entry = super(CythonScope, self).lookup(name)
|
| 48 |
+
|
| 49 |
+
return entry
|
| 50 |
+
|
| 51 |
+
def find_module(self, module_name, pos):
|
| 52 |
+
error("cython.%s is not available" % module_name, pos)
|
| 53 |
+
|
| 54 |
+
def find_submodule(self, module_name, as_package=False):
|
| 55 |
+
entry = self.entries.get(module_name, None)
|
| 56 |
+
if not entry:
|
| 57 |
+
self.load_cythonscope()
|
| 58 |
+
entry = self.entries.get(module_name, None)
|
| 59 |
+
|
| 60 |
+
if entry and entry.as_module:
|
| 61 |
+
return entry.as_module
|
| 62 |
+
else:
|
| 63 |
+
# TODO: fix find_submodule control flow so that we're not
|
| 64 |
+
# expected to create a submodule here (to protect CythonScope's
|
| 65 |
+
# possible immutability). Hack ourselves out of the situation
|
| 66 |
+
# for now.
|
| 67 |
+
raise error((StringSourceDescriptor(u"cython", u""), 0, 0),
|
| 68 |
+
"cython.%s is not available" % module_name)
|
| 69 |
+
|
| 70 |
+
def lookup_qualified_name(self, qname):
|
| 71 |
+
# ExprNode.as_cython_attribute generates qnames and we untangle it here...
|
| 72 |
+
name_path = qname.split(u'.')
|
| 73 |
+
scope = self
|
| 74 |
+
while len(name_path) > 1:
|
| 75 |
+
scope = scope.lookup_here(name_path[0])
|
| 76 |
+
if scope:
|
| 77 |
+
scope = scope.as_module
|
| 78 |
+
del name_path[0]
|
| 79 |
+
if scope is None:
|
| 80 |
+
return None
|
| 81 |
+
else:
|
| 82 |
+
return scope.lookup_here(name_path[0])
|
| 83 |
+
|
| 84 |
+
def populate_cython_scope(self):
|
| 85 |
+
# These are used to optimize isinstance in FinalOptimizePhase
|
| 86 |
+
type_object = self.declare_typedef(
|
| 87 |
+
'PyTypeObject',
|
| 88 |
+
base_type = c_void_type,
|
| 89 |
+
pos = None,
|
| 90 |
+
cname = 'PyTypeObject')
|
| 91 |
+
type_object.is_void = True
|
| 92 |
+
type_object_type = type_object.type
|
| 93 |
+
|
| 94 |
+
self.declare_cfunction(
|
| 95 |
+
'PyObject_TypeCheck',
|
| 96 |
+
CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
|
| 97 |
+
CFuncTypeArg("t", c_ptr_type(type_object_type), None)]),
|
| 98 |
+
pos = None,
|
| 99 |
+
defining = 1,
|
| 100 |
+
cname = 'PyObject_TypeCheck')
|
| 101 |
+
|
| 102 |
+
def load_cythonscope(self):
|
| 103 |
+
"""
|
| 104 |
+
Creates some entries for testing purposes and entries for
|
| 105 |
+
cython.array() and for cython.view.*.
|
| 106 |
+
"""
|
| 107 |
+
if self._cythonscope_initialized:
|
| 108 |
+
return
|
| 109 |
+
|
| 110 |
+
self._cythonscope_initialized = True
|
| 111 |
+
cython_testscope_utility_code.declare_in_scope(
|
| 112 |
+
self, cython_scope=self)
|
| 113 |
+
cython_test_extclass_utility_code.declare_in_scope(
|
| 114 |
+
self, cython_scope=self)
|
| 115 |
+
|
| 116 |
+
#
|
| 117 |
+
# The view sub-scope
|
| 118 |
+
#
|
| 119 |
+
self.viewscope = viewscope = ModuleScope(u'view', self, None)
|
| 120 |
+
self.declare_module('view', viewscope, None).as_module = viewscope
|
| 121 |
+
viewscope.is_cython_builtin = True
|
| 122 |
+
viewscope.pxd_file_loaded = True
|
| 123 |
+
|
| 124 |
+
cythonview_testscope_utility_code.declare_in_scope(
|
| 125 |
+
viewscope, cython_scope=self)
|
| 126 |
+
|
| 127 |
+
view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
|
| 128 |
+
self.viewscope, cython_scope=self,
|
| 129 |
+
allowlist=MemoryView.view_utility_allowlist)
|
| 130 |
+
|
| 131 |
+
# Marks the types as being cython_builtin_type so that they can be
|
| 132 |
+
# extended from without Cython attempting to import cython.view
|
| 133 |
+
ext_types = [ entry.type
|
| 134 |
+
for entry in view_utility_scope.entries.values()
|
| 135 |
+
if entry.type.is_extension_type ]
|
| 136 |
+
for ext_type in ext_types:
|
| 137 |
+
ext_type.is_cython_builtin_type = 1
|
| 138 |
+
|
| 139 |
+
# self.entries["array"] = view_utility_scope.entries.pop("array")
|
| 140 |
+
|
| 141 |
+
# dataclasses scope
|
| 142 |
+
dc_str = EncodedString(u'dataclasses')
|
| 143 |
+
dataclassesscope = ModuleScope(dc_str, self, context=None)
|
| 144 |
+
self.declare_module(dc_str, dataclassesscope, pos=None).as_module = dataclassesscope
|
| 145 |
+
dataclassesscope.is_cython_builtin = True
|
| 146 |
+
dataclassesscope.pxd_file_loaded = True
|
| 147 |
+
# doesn't actually have any contents
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def create_cython_scope(context):
|
| 151 |
+
# One could in fact probably make it a singleton,
|
| 152 |
+
# but not sure yet whether any code mutates it (which would kill reusing
|
| 153 |
+
# it across different contexts)
|
| 154 |
+
return CythonScope(context)
|
| 155 |
+
|
| 156 |
+
# Load test utilities for the cython scope
|
| 157 |
+
|
| 158 |
+
def load_testscope_utility(cy_util_name, **kwargs):
|
| 159 |
+
return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
undecorated_methods_protos = UtilityCode(proto=u"""
|
| 163 |
+
/* These methods are undecorated and have therefore no prototype */
|
| 164 |
+
static PyObject *__pyx_TestClass_cdef_method(
|
| 165 |
+
struct __pyx_TestClass_obj *self, int value);
|
| 166 |
+
static PyObject *__pyx_TestClass_cpdef_method(
|
| 167 |
+
struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
|
| 168 |
+
static PyObject *__pyx_TestClass_def_method(
|
| 169 |
+
PyObject *self, PyObject *value);
|
| 170 |
+
""")
|
| 171 |
+
|
| 172 |
+
cython_testscope_utility_code = load_testscope_utility("TestScope")
|
| 173 |
+
|
| 174 |
+
test_cython_utility_dep = load_testscope_utility("TestDep")
|
| 175 |
+
|
| 176 |
+
cython_test_extclass_utility_code = \
|
| 177 |
+
load_testscope_utility("TestClass", name="TestClass",
|
| 178 |
+
requires=[undecorated_methods_protos,
|
| 179 |
+
test_cython_utility_dep])
|
| 180 |
+
|
| 181 |
+
cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/ExprNodes.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FlowControl.pxd
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: language_level=3
|
| 2 |
+
|
| 3 |
+
cimport cython
|
| 4 |
+
|
| 5 |
+
from .Visitor cimport CythonTransform, TreeVisitor
|
| 6 |
+
|
| 7 |
+
cdef class ControlBlock:
|
| 8 |
+
cdef public set children
|
| 9 |
+
cdef public set parents
|
| 10 |
+
cdef public set positions
|
| 11 |
+
cdef public list stats
|
| 12 |
+
cdef public dict gen
|
| 13 |
+
cdef public set bounded
|
| 14 |
+
|
| 15 |
+
# Big integer bitsets
|
| 16 |
+
cdef public object i_input
|
| 17 |
+
cdef public object i_output
|
| 18 |
+
cdef public object i_gen
|
| 19 |
+
cdef public object i_kill
|
| 20 |
+
cdef public object i_state
|
| 21 |
+
|
| 22 |
+
cpdef bint empty(self)
|
| 23 |
+
cpdef detach(self)
|
| 24 |
+
cpdef add_child(self, block)
|
| 25 |
+
|
| 26 |
+
cdef class ExitBlock(ControlBlock):
|
| 27 |
+
cpdef bint empty(self)
|
| 28 |
+
|
| 29 |
+
cdef class NameAssignment:
|
| 30 |
+
cdef public bint is_arg
|
| 31 |
+
cdef public bint is_deletion
|
| 32 |
+
cdef public object lhs
|
| 33 |
+
cdef public object rhs
|
| 34 |
+
cdef public object entry
|
| 35 |
+
cdef public object pos
|
| 36 |
+
cdef public set refs
|
| 37 |
+
cdef public object bit
|
| 38 |
+
cdef public object inferred_type
|
| 39 |
+
cdef public object rhs_scope
|
| 40 |
+
|
| 41 |
+
cdef class AssignmentList:
|
| 42 |
+
cdef public object bit
|
| 43 |
+
cdef public object mask
|
| 44 |
+
cdef public list stats
|
| 45 |
+
|
| 46 |
+
cdef class AssignmentCollector(TreeVisitor):
|
| 47 |
+
cdef list assignments
|
| 48 |
+
|
| 49 |
+
@cython.final
|
| 50 |
+
cdef class ControlFlow:
|
| 51 |
+
cdef public set blocks
|
| 52 |
+
cdef public set entries
|
| 53 |
+
cdef public list loops
|
| 54 |
+
cdef public list exceptions
|
| 55 |
+
|
| 56 |
+
cdef public ControlBlock entry_point
|
| 57 |
+
cdef public ExitBlock exit_point
|
| 58 |
+
cdef public ControlBlock block
|
| 59 |
+
|
| 60 |
+
cdef public dict assmts
|
| 61 |
+
|
| 62 |
+
cdef public Py_ssize_t in_try_block
|
| 63 |
+
|
| 64 |
+
cpdef newblock(self, ControlBlock parent=*)
|
| 65 |
+
cpdef nextblock(self, ControlBlock parent=*)
|
| 66 |
+
cpdef bint is_tracked(self, entry)
|
| 67 |
+
cpdef bint is_statically_assigned(self, entry)
|
| 68 |
+
cpdef mark_position(self, node)
|
| 69 |
+
cpdef mark_assignment(self, lhs, rhs, entry, rhs_scope=*)
|
| 70 |
+
cpdef mark_argument(self, lhs, rhs, entry)
|
| 71 |
+
cpdef mark_deletion(self, node, entry)
|
| 72 |
+
cpdef mark_reference(self, node, entry)
|
| 73 |
+
|
| 74 |
+
@cython.locals(block=ControlBlock, parent=ControlBlock, unreachable=set)
|
| 75 |
+
cpdef normalize(self)
|
| 76 |
+
|
| 77 |
+
@cython.locals(bit=object, assmts=AssignmentList, block=ControlBlock)
|
| 78 |
+
cpdef initialize(self)
|
| 79 |
+
|
| 80 |
+
@cython.locals(assmts=AssignmentList, assmt=NameAssignment)
|
| 81 |
+
cpdef set map_one(self, istate, entry)
|
| 82 |
+
|
| 83 |
+
@cython.locals(block=ControlBlock, parent=ControlBlock)
|
| 84 |
+
cdef reaching_definitions(self)
|
| 85 |
+
|
| 86 |
+
cdef class Uninitialized:
|
| 87 |
+
pass
|
| 88 |
+
|
| 89 |
+
cdef class Unknown:
|
| 90 |
+
pass
|
| 91 |
+
|
| 92 |
+
cdef class MessageCollection:
|
| 93 |
+
cdef set messages
|
| 94 |
+
|
| 95 |
+
@cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock,
|
| 96 |
+
assmt=NameAssignment)
|
| 97 |
+
cdef check_definitions(ControlFlow flow, dict compiler_directives)
|
| 98 |
+
|
| 99 |
+
@cython.final
|
| 100 |
+
cdef class ControlFlowAnalysis(CythonTransform):
|
| 101 |
+
cdef object gv_ctx
|
| 102 |
+
cdef object constant_folder
|
| 103 |
+
cdef set reductions
|
| 104 |
+
cdef list stack # a stack of (env, flow) tuples
|
| 105 |
+
cdef object env
|
| 106 |
+
cdef ControlFlow flow
|
| 107 |
+
cdef object object_expr
|
| 108 |
+
cdef bint in_inplace_assignment
|
| 109 |
+
|
| 110 |
+
cpdef mark_assignment(self, lhs, rhs=*, rhs_scope=*)
|
| 111 |
+
cpdef mark_position(self, node)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/FlowControl.py
ADDED
|
@@ -0,0 +1,1383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: language_level=3str
|
| 2 |
+
# cython: auto_pickle=True
|
| 3 |
+
|
| 4 |
+
from __future__ import absolute_import
|
| 5 |
+
|
| 6 |
+
import cython
|
| 7 |
+
cython.declare(PyrexTypes=object, ExprNodes=object, Nodes=object, Builtin=object,
|
| 8 |
+
Options=object, TreeVisitor=object, CythonTransform=object,
|
| 9 |
+
InternalError=object, error=object, warning=object,
|
| 10 |
+
fake_rhs_expr=object, TypedExprNode=object)
|
| 11 |
+
|
| 12 |
+
from . import Builtin
|
| 13 |
+
from . import ExprNodes
|
| 14 |
+
from . import Nodes
|
| 15 |
+
from . import Options
|
| 16 |
+
from . import PyrexTypes
|
| 17 |
+
|
| 18 |
+
from .Visitor import TreeVisitor, CythonTransform
|
| 19 |
+
from .Errors import error, warning, InternalError
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class TypedExprNode(ExprNodes.ExprNode):
|
| 23 |
+
# Used for declaring assignments of a specified type without a known entry.
|
| 24 |
+
def __init__(self, type, may_be_none=None, pos=None):
|
| 25 |
+
super(TypedExprNode, self).__init__(pos)
|
| 26 |
+
self.type = type
|
| 27 |
+
self._may_be_none = may_be_none
|
| 28 |
+
|
| 29 |
+
def may_be_none(self):
|
| 30 |
+
return self._may_be_none != False
|
| 31 |
+
|
| 32 |
+
# Fake rhs to silence "unused variable" warning
|
| 33 |
+
fake_rhs_expr = TypedExprNode(PyrexTypes.unspecified_type)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class ControlBlock(object):
|
| 37 |
+
"""Control flow graph node. Sequence of assignments and name references.
|
| 38 |
+
|
| 39 |
+
children set of children nodes
|
| 40 |
+
parents set of parent nodes
|
| 41 |
+
positions set of position markers
|
| 42 |
+
|
| 43 |
+
stats list of block statements
|
| 44 |
+
gen dict of assignments generated by this block
|
| 45 |
+
bounded set of entries that are definitely bounded in this block
|
| 46 |
+
|
| 47 |
+
Example:
|
| 48 |
+
|
| 49 |
+
a = 1
|
| 50 |
+
b = a + c # 'c' is already bounded or exception here
|
| 51 |
+
|
| 52 |
+
stats = [Assignment(a), NameReference(a), NameReference(c),
|
| 53 |
+
Assignment(b)]
|
| 54 |
+
gen = {Entry(a): Assignment(a), Entry(b): Assignment(b)}
|
| 55 |
+
bounded = {Entry(a), Entry(c)}
|
| 56 |
+
|
| 57 |
+
"""
|
| 58 |
+
|
| 59 |
+
def __init__(self):
|
| 60 |
+
self.children = set()
|
| 61 |
+
self.parents = set()
|
| 62 |
+
self.positions = set()
|
| 63 |
+
|
| 64 |
+
self.stats = []
|
| 65 |
+
self.gen = {}
|
| 66 |
+
self.bounded = set()
|
| 67 |
+
|
| 68 |
+
self.i_input = 0
|
| 69 |
+
self.i_output = 0
|
| 70 |
+
self.i_gen = 0
|
| 71 |
+
self.i_kill = 0
|
| 72 |
+
self.i_state = 0
|
| 73 |
+
|
| 74 |
+
def empty(self):
|
| 75 |
+
return (not self.stats and not self.positions)
|
| 76 |
+
|
| 77 |
+
def detach(self):
|
| 78 |
+
"""Detach block from parents and children."""
|
| 79 |
+
for child in self.children:
|
| 80 |
+
child.parents.remove(self)
|
| 81 |
+
for parent in self.parents:
|
| 82 |
+
parent.children.remove(self)
|
| 83 |
+
self.parents.clear()
|
| 84 |
+
self.children.clear()
|
| 85 |
+
|
| 86 |
+
def add_child(self, block):
|
| 87 |
+
self.children.add(block)
|
| 88 |
+
block.parents.add(self)
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
class ExitBlock(ControlBlock):
|
| 92 |
+
"""Non-empty exit point block."""
|
| 93 |
+
|
| 94 |
+
def empty(self):
|
| 95 |
+
return False
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
class AssignmentList(object):
|
| 99 |
+
def __init__(self):
|
| 100 |
+
self.stats = []
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
class ControlFlow(object):
|
| 104 |
+
"""Control-flow graph.
|
| 105 |
+
|
| 106 |
+
entry_point ControlBlock entry point for this graph
|
| 107 |
+
exit_point ControlBlock normal exit point
|
| 108 |
+
block ControlBlock current block
|
| 109 |
+
blocks set children nodes
|
| 110 |
+
entries set tracked entries
|
| 111 |
+
loops list stack for loop descriptors
|
| 112 |
+
exceptions list stack for exception descriptors
|
| 113 |
+
in_try_block int track if we're in a try...except or try...finally block
|
| 114 |
+
"""
|
| 115 |
+
|
| 116 |
+
def __init__(self):
|
| 117 |
+
self.blocks = set()
|
| 118 |
+
self.entries = set()
|
| 119 |
+
self.loops = []
|
| 120 |
+
self.exceptions = []
|
| 121 |
+
|
| 122 |
+
self.entry_point = ControlBlock()
|
| 123 |
+
self.exit_point = ExitBlock()
|
| 124 |
+
self.blocks.add(self.exit_point)
|
| 125 |
+
self.block = self.entry_point
|
| 126 |
+
self.in_try_block = 0
|
| 127 |
+
|
| 128 |
+
def newblock(self, parent=None):
|
| 129 |
+
"""Create floating block linked to `parent` if given.
|
| 130 |
+
|
| 131 |
+
NOTE: Block is NOT added to self.blocks
|
| 132 |
+
"""
|
| 133 |
+
block = ControlBlock()
|
| 134 |
+
self.blocks.add(block)
|
| 135 |
+
if parent:
|
| 136 |
+
parent.add_child(block)
|
| 137 |
+
return block
|
| 138 |
+
|
| 139 |
+
def nextblock(self, parent=None):
|
| 140 |
+
"""Create block children block linked to current or `parent` if given.
|
| 141 |
+
|
| 142 |
+
NOTE: Block is added to self.blocks
|
| 143 |
+
"""
|
| 144 |
+
block = ControlBlock()
|
| 145 |
+
self.blocks.add(block)
|
| 146 |
+
if parent:
|
| 147 |
+
parent.add_child(block)
|
| 148 |
+
elif self.block:
|
| 149 |
+
self.block.add_child(block)
|
| 150 |
+
self.block = block
|
| 151 |
+
return self.block
|
| 152 |
+
|
| 153 |
+
def is_tracked(self, entry):
|
| 154 |
+
if entry.is_anonymous:
|
| 155 |
+
return False
|
| 156 |
+
return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or
|
| 157 |
+
entry.from_closure or entry.in_closure or
|
| 158 |
+
entry.error_on_uninitialized)
|
| 159 |
+
|
| 160 |
+
def is_statically_assigned(self, entry):
|
| 161 |
+
if (entry.is_local and entry.is_variable and
|
| 162 |
+
(entry.type.is_struct_or_union or
|
| 163 |
+
entry.type.is_complex or
|
| 164 |
+
entry.type.is_array or
|
| 165 |
+
(entry.type.is_cpp_class and not entry.is_cpp_optional))):
|
| 166 |
+
# stack allocated structured variable => never uninitialised
|
| 167 |
+
return True
|
| 168 |
+
return False
|
| 169 |
+
|
| 170 |
+
def mark_position(self, node):
|
| 171 |
+
"""Mark position, will be used to draw graph nodes."""
|
| 172 |
+
if self.block:
|
| 173 |
+
self.block.positions.add(node.pos[:2])
|
| 174 |
+
|
| 175 |
+
def mark_assignment(self, lhs, rhs, entry, rhs_scope=None):
|
| 176 |
+
if self.block and self.is_tracked(entry):
|
| 177 |
+
assignment = NameAssignment(lhs, rhs, entry, rhs_scope=rhs_scope)
|
| 178 |
+
self.block.stats.append(assignment)
|
| 179 |
+
self.block.gen[entry] = assignment
|
| 180 |
+
self.entries.add(entry)
|
| 181 |
+
|
| 182 |
+
def mark_argument(self, lhs, rhs, entry):
|
| 183 |
+
if self.block and self.is_tracked(entry):
|
| 184 |
+
assignment = Argument(lhs, rhs, entry)
|
| 185 |
+
self.block.stats.append(assignment)
|
| 186 |
+
self.block.gen[entry] = assignment
|
| 187 |
+
self.entries.add(entry)
|
| 188 |
+
|
| 189 |
+
def mark_deletion(self, node, entry):
|
| 190 |
+
if self.block and self.is_tracked(entry):
|
| 191 |
+
assignment = NameDeletion(node, entry)
|
| 192 |
+
self.block.stats.append(assignment)
|
| 193 |
+
self.block.gen[entry] = Uninitialized
|
| 194 |
+
self.entries.add(entry)
|
| 195 |
+
|
| 196 |
+
def mark_reference(self, node, entry):
|
| 197 |
+
if self.block and self.is_tracked(entry):
|
| 198 |
+
self.block.stats.append(NameReference(node, entry))
|
| 199 |
+
## XXX: We don't track expression evaluation order so we can't use
|
| 200 |
+
## XXX: successful reference as initialization sign.
|
| 201 |
+
## # Local variable is definitely bound after this reference
|
| 202 |
+
## if not node.allow_null:
|
| 203 |
+
## self.block.bounded.add(entry)
|
| 204 |
+
self.entries.add(entry)
|
| 205 |
+
|
| 206 |
+
def normalize(self):
|
| 207 |
+
"""Delete unreachable and orphan blocks."""
|
| 208 |
+
queue = {self.entry_point}
|
| 209 |
+
visited = set()
|
| 210 |
+
while queue:
|
| 211 |
+
root = queue.pop()
|
| 212 |
+
visited.add(root)
|
| 213 |
+
for child in root.children:
|
| 214 |
+
if child not in visited:
|
| 215 |
+
queue.add(child)
|
| 216 |
+
unreachable = self.blocks - visited
|
| 217 |
+
for block in unreachable:
|
| 218 |
+
block.detach()
|
| 219 |
+
visited.remove(self.entry_point)
|
| 220 |
+
for block in visited:
|
| 221 |
+
if block.empty():
|
| 222 |
+
for parent in block.parents: # Re-parent
|
| 223 |
+
for child in block.children:
|
| 224 |
+
parent.add_child(child)
|
| 225 |
+
block.detach()
|
| 226 |
+
unreachable.add(block)
|
| 227 |
+
self.blocks -= unreachable
|
| 228 |
+
|
| 229 |
+
def initialize(self):
|
| 230 |
+
"""Set initial state, map assignments to bits."""
|
| 231 |
+
self.assmts = {}
|
| 232 |
+
|
| 233 |
+
bit = 1
|
| 234 |
+
for entry in self.entries:
|
| 235 |
+
assmts = AssignmentList()
|
| 236 |
+
assmts.mask = assmts.bit = bit
|
| 237 |
+
self.assmts[entry] = assmts
|
| 238 |
+
bit <<= 1
|
| 239 |
+
|
| 240 |
+
for block in self.blocks:
|
| 241 |
+
for stat in block.stats:
|
| 242 |
+
if isinstance(stat, NameAssignment):
|
| 243 |
+
stat.bit = bit
|
| 244 |
+
assmts = self.assmts[stat.entry]
|
| 245 |
+
assmts.stats.append(stat)
|
| 246 |
+
assmts.mask |= bit
|
| 247 |
+
bit <<= 1
|
| 248 |
+
|
| 249 |
+
for block in self.blocks:
|
| 250 |
+
for entry, stat in block.gen.items():
|
| 251 |
+
assmts = self.assmts[entry]
|
| 252 |
+
if stat is Uninitialized:
|
| 253 |
+
block.i_gen |= assmts.bit
|
| 254 |
+
else:
|
| 255 |
+
block.i_gen |= stat.bit
|
| 256 |
+
block.i_kill |= assmts.mask
|
| 257 |
+
block.i_output = block.i_gen
|
| 258 |
+
for entry in block.bounded:
|
| 259 |
+
block.i_kill |= self.assmts[entry].bit
|
| 260 |
+
|
| 261 |
+
for assmts in self.assmts.values():
|
| 262 |
+
self.entry_point.i_gen |= assmts.bit
|
| 263 |
+
self.entry_point.i_output = self.entry_point.i_gen
|
| 264 |
+
|
| 265 |
+
def map_one(self, istate, entry):
|
| 266 |
+
ret = set()
|
| 267 |
+
assmts = self.assmts[entry]
|
| 268 |
+
if istate & assmts.bit:
|
| 269 |
+
if self.is_statically_assigned(entry):
|
| 270 |
+
ret.add(StaticAssignment(entry))
|
| 271 |
+
elif entry.from_closure:
|
| 272 |
+
ret.add(Unknown)
|
| 273 |
+
else:
|
| 274 |
+
ret.add(Uninitialized)
|
| 275 |
+
for assmt in assmts.stats:
|
| 276 |
+
if istate & assmt.bit:
|
| 277 |
+
ret.add(assmt)
|
| 278 |
+
return ret
|
| 279 |
+
|
| 280 |
+
def reaching_definitions(self):
|
| 281 |
+
"""Per-block reaching definitions analysis."""
|
| 282 |
+
dirty = True
|
| 283 |
+
while dirty:
|
| 284 |
+
dirty = False
|
| 285 |
+
for block in self.blocks:
|
| 286 |
+
i_input = 0
|
| 287 |
+
for parent in block.parents:
|
| 288 |
+
i_input |= parent.i_output
|
| 289 |
+
i_output = (i_input & ~block.i_kill) | block.i_gen
|
| 290 |
+
if i_output != block.i_output:
|
| 291 |
+
dirty = True
|
| 292 |
+
block.i_input = i_input
|
| 293 |
+
block.i_output = i_output
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
class LoopDescr(object):
|
| 297 |
+
def __init__(self, next_block, loop_block):
|
| 298 |
+
self.next_block = next_block
|
| 299 |
+
self.loop_block = loop_block
|
| 300 |
+
self.exceptions = []
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
class ExceptionDescr(object):
|
| 304 |
+
"""Exception handling helper.
|
| 305 |
+
|
| 306 |
+
entry_point ControlBlock Exception handling entry point
|
| 307 |
+
finally_enter ControlBlock Normal finally clause entry point
|
| 308 |
+
finally_exit ControlBlock Normal finally clause exit point
|
| 309 |
+
"""
|
| 310 |
+
|
| 311 |
+
def __init__(self, entry_point, finally_enter=None, finally_exit=None):
|
| 312 |
+
self.entry_point = entry_point
|
| 313 |
+
self.finally_enter = finally_enter
|
| 314 |
+
self.finally_exit = finally_exit
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
class NameAssignment(object):
|
| 318 |
+
def __init__(self, lhs, rhs, entry, rhs_scope=None):
|
| 319 |
+
if lhs.cf_state is None:
|
| 320 |
+
lhs.cf_state = set()
|
| 321 |
+
self.lhs = lhs
|
| 322 |
+
self.rhs = rhs
|
| 323 |
+
self.entry = entry
|
| 324 |
+
self.pos = lhs.pos
|
| 325 |
+
self.refs = set()
|
| 326 |
+
self.is_arg = False
|
| 327 |
+
self.is_deletion = False
|
| 328 |
+
self.inferred_type = None
|
| 329 |
+
# For generator expression targets, the rhs can have a different scope than the lhs.
|
| 330 |
+
self.rhs_scope = rhs_scope
|
| 331 |
+
|
| 332 |
+
def __repr__(self):
|
| 333 |
+
return '%s(entry=%r)' % (self.__class__.__name__, self.entry)
|
| 334 |
+
|
| 335 |
+
def infer_type(self):
|
| 336 |
+
self.inferred_type = self.rhs.infer_type(self.rhs_scope or self.entry.scope)
|
| 337 |
+
return self.inferred_type
|
| 338 |
+
|
| 339 |
+
def type_dependencies(self):
|
| 340 |
+
return self.rhs.type_dependencies(self.rhs_scope or self.entry.scope)
|
| 341 |
+
|
| 342 |
+
@property
|
| 343 |
+
def type(self):
|
| 344 |
+
if not self.entry.type.is_unspecified:
|
| 345 |
+
return self.entry.type
|
| 346 |
+
return self.inferred_type
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
class StaticAssignment(NameAssignment):
|
| 350 |
+
"""Initialised at declaration time, e.g. stack allocation."""
|
| 351 |
+
def __init__(self, entry):
|
| 352 |
+
if not entry.type.is_pyobject:
|
| 353 |
+
may_be_none = False
|
| 354 |
+
else:
|
| 355 |
+
may_be_none = None # unknown
|
| 356 |
+
lhs = TypedExprNode(
|
| 357 |
+
entry.type, may_be_none=may_be_none, pos=entry.pos)
|
| 358 |
+
super(StaticAssignment, self).__init__(lhs, lhs, entry)
|
| 359 |
+
|
| 360 |
+
def infer_type(self):
|
| 361 |
+
return self.entry.type
|
| 362 |
+
|
| 363 |
+
def type_dependencies(self):
|
| 364 |
+
return ()
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
class Argument(NameAssignment):
|
| 368 |
+
def __init__(self, lhs, rhs, entry):
|
| 369 |
+
NameAssignment.__init__(self, lhs, rhs, entry)
|
| 370 |
+
self.is_arg = True
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
class NameDeletion(NameAssignment):
|
| 374 |
+
def __init__(self, lhs, entry):
|
| 375 |
+
NameAssignment.__init__(self, lhs, lhs, entry)
|
| 376 |
+
self.is_deletion = True
|
| 377 |
+
|
| 378 |
+
def infer_type(self):
|
| 379 |
+
inferred_type = self.rhs.infer_type(self.entry.scope)
|
| 380 |
+
if (not inferred_type.is_pyobject
|
| 381 |
+
and inferred_type.can_coerce_to_pyobject(self.entry.scope)):
|
| 382 |
+
return PyrexTypes.py_object_type
|
| 383 |
+
self.inferred_type = inferred_type
|
| 384 |
+
return inferred_type
|
| 385 |
+
|
| 386 |
+
|
| 387 |
+
class Uninitialized(object):
|
| 388 |
+
"""Definitely not initialised yet."""
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
class Unknown(object):
|
| 392 |
+
"""Coming from outer closure, might be initialised or not."""
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
class NameReference(object):
|
| 396 |
+
def __init__(self, node, entry):
|
| 397 |
+
if node.cf_state is None:
|
| 398 |
+
node.cf_state = set()
|
| 399 |
+
self.node = node
|
| 400 |
+
self.entry = entry
|
| 401 |
+
self.pos = node.pos
|
| 402 |
+
|
| 403 |
+
def __repr__(self):
|
| 404 |
+
return '%s(entry=%r)' % (self.__class__.__name__, self.entry)
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
class ControlFlowState(list):
|
| 408 |
+
# Keeps track of Node's entry assignments
|
| 409 |
+
#
|
| 410 |
+
# cf_is_null [boolean] It is uninitialized
|
| 411 |
+
# cf_maybe_null [boolean] May be uninitialized
|
| 412 |
+
# is_single [boolean] Has only one assignment at this point
|
| 413 |
+
|
| 414 |
+
cf_maybe_null = False
|
| 415 |
+
cf_is_null = False
|
| 416 |
+
is_single = False
|
| 417 |
+
|
| 418 |
+
def __init__(self, state):
|
| 419 |
+
if Uninitialized in state:
|
| 420 |
+
state.discard(Uninitialized)
|
| 421 |
+
self.cf_maybe_null = True
|
| 422 |
+
if not state:
|
| 423 |
+
self.cf_is_null = True
|
| 424 |
+
elif Unknown in state:
|
| 425 |
+
state.discard(Unknown)
|
| 426 |
+
self.cf_maybe_null = True
|
| 427 |
+
else:
|
| 428 |
+
if len(state) == 1:
|
| 429 |
+
self.is_single = True
|
| 430 |
+
# XXX: Remove fake_rhs_expr
|
| 431 |
+
super(ControlFlowState, self).__init__(
|
| 432 |
+
[i for i in state if i.rhs is not fake_rhs_expr])
|
| 433 |
+
|
| 434 |
+
def one(self):
|
| 435 |
+
return self[0]
|
| 436 |
+
|
| 437 |
+
|
| 438 |
+
class GVContext(object):
|
| 439 |
+
"""Graphviz subgraph object."""
|
| 440 |
+
|
| 441 |
+
def __init__(self):
|
| 442 |
+
self.blockids = {}
|
| 443 |
+
self.nextid = 0
|
| 444 |
+
self.children = []
|
| 445 |
+
self.sources = {}
|
| 446 |
+
|
| 447 |
+
def add(self, child):
|
| 448 |
+
self.children.append(child)
|
| 449 |
+
|
| 450 |
+
def nodeid(self, block):
|
| 451 |
+
if block not in self.blockids:
|
| 452 |
+
self.blockids[block] = 'block%d' % self.nextid
|
| 453 |
+
self.nextid += 1
|
| 454 |
+
return self.blockids[block]
|
| 455 |
+
|
| 456 |
+
def extract_sources(self, block):
|
| 457 |
+
if not block.positions:
|
| 458 |
+
return ''
|
| 459 |
+
start = min(block.positions)
|
| 460 |
+
stop = max(block.positions)
|
| 461 |
+
srcdescr = start[0]
|
| 462 |
+
if srcdescr not in self.sources:
|
| 463 |
+
self.sources[srcdescr] = list(srcdescr.get_lines())
|
| 464 |
+
lines = self.sources[srcdescr]
|
| 465 |
+
return '\\n'.join([l.strip() for l in lines[start[1] - 1:stop[1]]])
|
| 466 |
+
|
| 467 |
+
def render(self, fp, name, annotate_defs=False):
|
| 468 |
+
"""Render graphviz dot graph"""
|
| 469 |
+
fp.write('digraph %s {\n' % name)
|
| 470 |
+
fp.write(' node [shape=box];\n')
|
| 471 |
+
for child in self.children:
|
| 472 |
+
child.render(fp, self, annotate_defs)
|
| 473 |
+
fp.write('}\n')
|
| 474 |
+
|
| 475 |
+
def escape(self, text):
|
| 476 |
+
return text.replace('"', '\\"').replace('\n', '\\n')
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
class GV(object):
|
| 480 |
+
"""Graphviz DOT renderer."""
|
| 481 |
+
|
| 482 |
+
def __init__(self, name, flow):
|
| 483 |
+
self.name = name
|
| 484 |
+
self.flow = flow
|
| 485 |
+
|
| 486 |
+
def render(self, fp, ctx, annotate_defs=False):
|
| 487 |
+
fp.write(' subgraph %s {\n' % self.name)
|
| 488 |
+
for block in self.flow.blocks:
|
| 489 |
+
label = ctx.extract_sources(block)
|
| 490 |
+
if annotate_defs:
|
| 491 |
+
for stat in block.stats:
|
| 492 |
+
if isinstance(stat, NameAssignment):
|
| 493 |
+
label += '\n %s [%s %s]' % (
|
| 494 |
+
stat.entry.name, 'deletion' if stat.is_deletion else 'definition', stat.pos[1])
|
| 495 |
+
elif isinstance(stat, NameReference):
|
| 496 |
+
if stat.entry:
|
| 497 |
+
label += '\n %s [reference %s]' % (stat.entry.name, stat.pos[1])
|
| 498 |
+
if not label:
|
| 499 |
+
label = 'empty'
|
| 500 |
+
pid = ctx.nodeid(block)
|
| 501 |
+
fp.write(' %s [label="%s"];\n' % (pid, ctx.escape(label)))
|
| 502 |
+
for block in self.flow.blocks:
|
| 503 |
+
pid = ctx.nodeid(block)
|
| 504 |
+
for child in block.children:
|
| 505 |
+
fp.write(' %s -> %s;\n' % (pid, ctx.nodeid(child)))
|
| 506 |
+
fp.write(' }\n')
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
class MessageCollection(object):
|
| 510 |
+
"""Collect error/warnings messages first then sort"""
|
| 511 |
+
def __init__(self):
|
| 512 |
+
self.messages = set()
|
| 513 |
+
|
| 514 |
+
def error(self, pos, message):
|
| 515 |
+
self.messages.add((pos, True, message))
|
| 516 |
+
|
| 517 |
+
def warning(self, pos, message):
|
| 518 |
+
self.messages.add((pos, False, message))
|
| 519 |
+
|
| 520 |
+
def report(self):
|
| 521 |
+
for pos, is_error, message in sorted(self.messages):
|
| 522 |
+
if is_error:
|
| 523 |
+
error(pos, message)
|
| 524 |
+
else:
|
| 525 |
+
warning(pos, message, 2)
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
def check_definitions(flow, compiler_directives):
|
| 529 |
+
flow.initialize()
|
| 530 |
+
flow.reaching_definitions()
|
| 531 |
+
|
| 532 |
+
# Track down state
|
| 533 |
+
assignments = set()
|
| 534 |
+
# Node to entry map
|
| 535 |
+
references = {}
|
| 536 |
+
assmt_nodes = set()
|
| 537 |
+
|
| 538 |
+
for block in flow.blocks:
|
| 539 |
+
i_state = block.i_input
|
| 540 |
+
for stat in block.stats:
|
| 541 |
+
i_assmts = flow.assmts[stat.entry]
|
| 542 |
+
state = flow.map_one(i_state, stat.entry)
|
| 543 |
+
if isinstance(stat, NameAssignment):
|
| 544 |
+
stat.lhs.cf_state.update(state)
|
| 545 |
+
assmt_nodes.add(stat.lhs)
|
| 546 |
+
i_state = i_state & ~i_assmts.mask
|
| 547 |
+
if stat.is_deletion:
|
| 548 |
+
i_state |= i_assmts.bit
|
| 549 |
+
else:
|
| 550 |
+
i_state |= stat.bit
|
| 551 |
+
assignments.add(stat)
|
| 552 |
+
if stat.rhs is not fake_rhs_expr:
|
| 553 |
+
stat.entry.cf_assignments.append(stat)
|
| 554 |
+
elif isinstance(stat, NameReference):
|
| 555 |
+
references[stat.node] = stat.entry
|
| 556 |
+
stat.entry.cf_references.append(stat)
|
| 557 |
+
stat.node.cf_state.update(state)
|
| 558 |
+
## if not stat.node.allow_null:
|
| 559 |
+
## i_state &= ~i_assmts.bit
|
| 560 |
+
## # after successful read, the state is known to be initialised
|
| 561 |
+
state.discard(Uninitialized)
|
| 562 |
+
state.discard(Unknown)
|
| 563 |
+
for assmt in state:
|
| 564 |
+
assmt.refs.add(stat)
|
| 565 |
+
|
| 566 |
+
# Check variable usage
|
| 567 |
+
warn_maybe_uninitialized = compiler_directives['warn.maybe_uninitialized']
|
| 568 |
+
warn_unused_result = compiler_directives['warn.unused_result']
|
| 569 |
+
warn_unused = compiler_directives['warn.unused']
|
| 570 |
+
warn_unused_arg = compiler_directives['warn.unused_arg']
|
| 571 |
+
|
| 572 |
+
messages = MessageCollection()
|
| 573 |
+
|
| 574 |
+
# assignment hints
|
| 575 |
+
for node in assmt_nodes:
|
| 576 |
+
if Uninitialized in node.cf_state:
|
| 577 |
+
node.cf_maybe_null = True
|
| 578 |
+
if len(node.cf_state) == 1:
|
| 579 |
+
node.cf_is_null = True
|
| 580 |
+
else:
|
| 581 |
+
node.cf_is_null = False
|
| 582 |
+
elif Unknown in node.cf_state:
|
| 583 |
+
node.cf_maybe_null = True
|
| 584 |
+
else:
|
| 585 |
+
node.cf_is_null = False
|
| 586 |
+
node.cf_maybe_null = False
|
| 587 |
+
|
| 588 |
+
# Find uninitialized references and cf-hints
|
| 589 |
+
for node, entry in references.items():
|
| 590 |
+
if Uninitialized in node.cf_state:
|
| 591 |
+
node.cf_maybe_null = True
|
| 592 |
+
if (not entry.from_closure and len(node.cf_state) == 1
|
| 593 |
+
and entry.name not in entry.scope.scope_predefined_names):
|
| 594 |
+
node.cf_is_null = True
|
| 595 |
+
if (node.allow_null or entry.from_closure
|
| 596 |
+
or entry.is_pyclass_attr or entry.type.is_error):
|
| 597 |
+
pass # Can be uninitialized here
|
| 598 |
+
elif node.cf_is_null and not entry.in_closure:
|
| 599 |
+
if entry.error_on_uninitialized or (
|
| 600 |
+
Options.error_on_uninitialized and (
|
| 601 |
+
entry.type.is_pyobject or entry.type.is_unspecified)):
|
| 602 |
+
messages.error(
|
| 603 |
+
node.pos,
|
| 604 |
+
"local variable '%s' referenced before assignment"
|
| 605 |
+
% entry.name)
|
| 606 |
+
else:
|
| 607 |
+
messages.warning(
|
| 608 |
+
node.pos,
|
| 609 |
+
"local variable '%s' referenced before assignment"
|
| 610 |
+
% entry.name)
|
| 611 |
+
elif warn_maybe_uninitialized:
|
| 612 |
+
msg = "local variable '%s' might be referenced before assignment" % entry.name
|
| 613 |
+
if entry.in_closure:
|
| 614 |
+
msg += " (maybe initialized inside a closure)"
|
| 615 |
+
messages.warning(
|
| 616 |
+
node.pos,
|
| 617 |
+
msg)
|
| 618 |
+
elif Unknown in node.cf_state:
|
| 619 |
+
# TODO: better cross-closure analysis to know when inner functions
|
| 620 |
+
# are being called before a variable is being set, and when
|
| 621 |
+
# a variable is known to be set before even defining the
|
| 622 |
+
# inner function, etc.
|
| 623 |
+
node.cf_maybe_null = True
|
| 624 |
+
else:
|
| 625 |
+
node.cf_is_null = False
|
| 626 |
+
node.cf_maybe_null = False
|
| 627 |
+
|
| 628 |
+
# Unused result
|
| 629 |
+
for assmt in assignments:
|
| 630 |
+
if (not assmt.refs and not assmt.entry.is_pyclass_attr
|
| 631 |
+
and not assmt.entry.in_closure):
|
| 632 |
+
if assmt.entry.cf_references and warn_unused_result:
|
| 633 |
+
if assmt.is_arg:
|
| 634 |
+
messages.warning(assmt.pos, "Unused argument value '%s'" %
|
| 635 |
+
assmt.entry.name)
|
| 636 |
+
else:
|
| 637 |
+
messages.warning(assmt.pos, "Unused result in '%s'" %
|
| 638 |
+
assmt.entry.name)
|
| 639 |
+
assmt.lhs.cf_used = False
|
| 640 |
+
|
| 641 |
+
# Unused entries
|
| 642 |
+
for entry in flow.entries:
|
| 643 |
+
if (not entry.cf_references
|
| 644 |
+
and not entry.is_pyclass_attr):
|
| 645 |
+
if entry.name != '_' and not entry.name.startswith('unused'):
|
| 646 |
+
# '_' is often used for unused variables, e.g. in loops
|
| 647 |
+
if entry.is_arg:
|
| 648 |
+
if warn_unused_arg:
|
| 649 |
+
messages.warning(entry.pos, "Unused argument '%s'" %
|
| 650 |
+
entry.name)
|
| 651 |
+
else:
|
| 652 |
+
if warn_unused:
|
| 653 |
+
messages.warning(entry.pos, "Unused entry '%s'" %
|
| 654 |
+
entry.name)
|
| 655 |
+
entry.cf_used = False
|
| 656 |
+
|
| 657 |
+
messages.report()
|
| 658 |
+
|
| 659 |
+
for node in assmt_nodes:
|
| 660 |
+
node.cf_state = ControlFlowState(node.cf_state)
|
| 661 |
+
for node in references:
|
| 662 |
+
node.cf_state = ControlFlowState(node.cf_state)
|
| 663 |
+
|
| 664 |
+
|
| 665 |
+
class AssignmentCollector(TreeVisitor):
|
| 666 |
+
def __init__(self):
|
| 667 |
+
super(AssignmentCollector, self).__init__()
|
| 668 |
+
self.assignments = []
|
| 669 |
+
|
| 670 |
+
def visit_Node(self):
|
| 671 |
+
self._visitchildren(self, None, None)
|
| 672 |
+
|
| 673 |
+
def visit_SingleAssignmentNode(self, node):
|
| 674 |
+
self.assignments.append((node.lhs, node.rhs))
|
| 675 |
+
|
| 676 |
+
def visit_CascadedAssignmentNode(self, node):
|
| 677 |
+
for lhs in node.lhs_list:
|
| 678 |
+
self.assignments.append((lhs, node.rhs))
|
| 679 |
+
|
| 680 |
+
|
| 681 |
+
class ControlFlowAnalysis(CythonTransform):
|
| 682 |
+
|
| 683 |
+
def find_in_stack(self, env):
|
| 684 |
+
if env == self.env:
|
| 685 |
+
return self.flow
|
| 686 |
+
for e, flow in reversed(self.stack):
|
| 687 |
+
if e is env:
|
| 688 |
+
return flow
|
| 689 |
+
assert False
|
| 690 |
+
|
| 691 |
+
def visit_ModuleNode(self, node):
|
| 692 |
+
dot_output = self.current_directives['control_flow.dot_output']
|
| 693 |
+
self.gv_ctx = GVContext() if dot_output else None
|
| 694 |
+
|
| 695 |
+
from .Optimize import ConstantFolding
|
| 696 |
+
self.constant_folder = ConstantFolding()
|
| 697 |
+
|
| 698 |
+
# Set of NameNode reductions
|
| 699 |
+
self.reductions = set()
|
| 700 |
+
|
| 701 |
+
self.in_inplace_assignment = False
|
| 702 |
+
self.env = node.scope
|
| 703 |
+
self.flow = ControlFlow()
|
| 704 |
+
self.stack = [] # a stack of (env, flow) tuples
|
| 705 |
+
self.object_expr = TypedExprNode(PyrexTypes.py_object_type, may_be_none=True)
|
| 706 |
+
self.visitchildren(node)
|
| 707 |
+
|
| 708 |
+
check_definitions(self.flow, self.current_directives)
|
| 709 |
+
|
| 710 |
+
if dot_output:
|
| 711 |
+
annotate_defs = self.current_directives['control_flow.dot_annotate_defs']
|
| 712 |
+
with open(dot_output, 'wt') as fp:
|
| 713 |
+
self.gv_ctx.render(fp, 'module', annotate_defs=annotate_defs)
|
| 714 |
+
return node
|
| 715 |
+
|
| 716 |
+
def visit_FuncDefNode(self, node):
|
| 717 |
+
for arg in node.args:
|
| 718 |
+
if arg.default:
|
| 719 |
+
self.visitchildren(arg)
|
| 720 |
+
self.visitchildren(node, ('decorators',))
|
| 721 |
+
self.stack.append((self.env, self.flow))
|
| 722 |
+
self.env = node.local_scope
|
| 723 |
+
self.flow = ControlFlow()
|
| 724 |
+
|
| 725 |
+
# Collect all entries
|
| 726 |
+
for entry in node.local_scope.entries.values():
|
| 727 |
+
if self.flow.is_tracked(entry):
|
| 728 |
+
self.flow.entries.add(entry)
|
| 729 |
+
|
| 730 |
+
self.mark_position(node)
|
| 731 |
+
# Function body block
|
| 732 |
+
self.flow.nextblock()
|
| 733 |
+
|
| 734 |
+
for arg in node.args:
|
| 735 |
+
self._visit(arg)
|
| 736 |
+
if node.star_arg:
|
| 737 |
+
self.flow.mark_argument(node.star_arg,
|
| 738 |
+
TypedExprNode(Builtin.tuple_type,
|
| 739 |
+
may_be_none=False),
|
| 740 |
+
node.star_arg.entry)
|
| 741 |
+
if node.starstar_arg:
|
| 742 |
+
self.flow.mark_argument(node.starstar_arg,
|
| 743 |
+
TypedExprNode(Builtin.dict_type,
|
| 744 |
+
may_be_none=False),
|
| 745 |
+
node.starstar_arg.entry)
|
| 746 |
+
self._visit(node.body)
|
| 747 |
+
# Workaround for generators
|
| 748 |
+
if node.is_generator:
|
| 749 |
+
self._visit(node.gbody.body)
|
| 750 |
+
|
| 751 |
+
# Exit point
|
| 752 |
+
if self.flow.block:
|
| 753 |
+
self.flow.block.add_child(self.flow.exit_point)
|
| 754 |
+
|
| 755 |
+
# Cleanup graph
|
| 756 |
+
self.flow.normalize()
|
| 757 |
+
check_definitions(self.flow, self.current_directives)
|
| 758 |
+
self.flow.blocks.add(self.flow.entry_point)
|
| 759 |
+
|
| 760 |
+
if self.gv_ctx is not None:
|
| 761 |
+
self.gv_ctx.add(GV(node.local_scope.name, self.flow))
|
| 762 |
+
|
| 763 |
+
self.env, self.flow = self.stack.pop()
|
| 764 |
+
return node
|
| 765 |
+
|
| 766 |
+
def visit_DefNode(self, node):
|
| 767 |
+
node.used = True
|
| 768 |
+
return self.visit_FuncDefNode(node)
|
| 769 |
+
|
| 770 |
+
def visit_GeneratorBodyDefNode(self, node):
|
| 771 |
+
return node
|
| 772 |
+
|
| 773 |
+
def visit_CTypeDefNode(self, node):
|
| 774 |
+
return node
|
| 775 |
+
|
| 776 |
+
def mark_assignment(self, lhs, rhs=None, rhs_scope=None):
|
| 777 |
+
if not self.flow.block:
|
| 778 |
+
return
|
| 779 |
+
if self.flow.exceptions:
|
| 780 |
+
exc_descr = self.flow.exceptions[-1]
|
| 781 |
+
self.flow.block.add_child(exc_descr.entry_point)
|
| 782 |
+
self.flow.nextblock()
|
| 783 |
+
|
| 784 |
+
if not rhs:
|
| 785 |
+
rhs = self.object_expr
|
| 786 |
+
if lhs.is_name:
|
| 787 |
+
if lhs.entry is not None:
|
| 788 |
+
entry = lhs.entry
|
| 789 |
+
else:
|
| 790 |
+
entry = self.env.lookup(lhs.name)
|
| 791 |
+
if entry is None: # TODO: This shouldn't happen...
|
| 792 |
+
return
|
| 793 |
+
self.flow.mark_assignment(lhs, rhs, entry, rhs_scope=rhs_scope)
|
| 794 |
+
elif lhs.is_sequence_constructor:
|
| 795 |
+
for i, arg in enumerate(lhs.args):
|
| 796 |
+
if arg.is_starred:
|
| 797 |
+
# "a, *b = x" assigns a list to "b"
|
| 798 |
+
item_node = TypedExprNode(Builtin.list_type, may_be_none=False, pos=arg.pos)
|
| 799 |
+
elif rhs is self.object_expr:
|
| 800 |
+
item_node = rhs
|
| 801 |
+
else:
|
| 802 |
+
item_node = rhs.inferable_item_node(i)
|
| 803 |
+
self.mark_assignment(arg, item_node)
|
| 804 |
+
else:
|
| 805 |
+
self._visit(lhs)
|
| 806 |
+
|
| 807 |
+
if self.flow.exceptions:
|
| 808 |
+
exc_descr = self.flow.exceptions[-1]
|
| 809 |
+
self.flow.block.add_child(exc_descr.entry_point)
|
| 810 |
+
self.flow.nextblock()
|
| 811 |
+
|
| 812 |
+
def mark_position(self, node):
|
| 813 |
+
"""Mark position if DOT output is enabled."""
|
| 814 |
+
if self.current_directives['control_flow.dot_output']:
|
| 815 |
+
self.flow.mark_position(node)
|
| 816 |
+
|
| 817 |
+
def visit_FromImportStatNode(self, node):
|
| 818 |
+
for name, target in node.items:
|
| 819 |
+
if name != "*":
|
| 820 |
+
self.mark_assignment(target)
|
| 821 |
+
self.visitchildren(node)
|
| 822 |
+
return node
|
| 823 |
+
|
| 824 |
+
def visit_AssignmentNode(self, node):
|
| 825 |
+
raise InternalError("Unhandled assignment node %s" % type(node))
|
| 826 |
+
|
| 827 |
+
def visit_SingleAssignmentNode(self, node):
|
| 828 |
+
self._visit(node.rhs)
|
| 829 |
+
self.mark_assignment(node.lhs, node.rhs)
|
| 830 |
+
return node
|
| 831 |
+
|
| 832 |
+
def visit_CascadedAssignmentNode(self, node):
|
| 833 |
+
self._visit(node.rhs)
|
| 834 |
+
for lhs in node.lhs_list:
|
| 835 |
+
self.mark_assignment(lhs, node.rhs)
|
| 836 |
+
return node
|
| 837 |
+
|
| 838 |
+
def visit_ParallelAssignmentNode(self, node):
|
| 839 |
+
collector = AssignmentCollector()
|
| 840 |
+
collector.visitchildren(node)
|
| 841 |
+
for lhs, rhs in collector.assignments:
|
| 842 |
+
self._visit(rhs)
|
| 843 |
+
for lhs, rhs in collector.assignments:
|
| 844 |
+
self.mark_assignment(lhs, rhs)
|
| 845 |
+
return node
|
| 846 |
+
|
| 847 |
+
def visit_InPlaceAssignmentNode(self, node):
|
| 848 |
+
self.in_inplace_assignment = True
|
| 849 |
+
self.visitchildren(node)
|
| 850 |
+
self.in_inplace_assignment = False
|
| 851 |
+
self.mark_assignment(node.lhs, self.constant_folder(node.create_binop_node()))
|
| 852 |
+
return node
|
| 853 |
+
|
| 854 |
+
def visit_DelStatNode(self, node):
|
| 855 |
+
for arg in node.args:
|
| 856 |
+
if arg.is_name:
|
| 857 |
+
entry = arg.entry or self.env.lookup(arg.name)
|
| 858 |
+
if entry.in_closure or entry.from_closure:
|
| 859 |
+
error(arg.pos,
|
| 860 |
+
"can not delete variable '%s' "
|
| 861 |
+
"referenced in nested scope" % entry.name)
|
| 862 |
+
if not node.ignore_nonexisting:
|
| 863 |
+
self._visit(arg) # mark reference
|
| 864 |
+
self.flow.mark_deletion(arg, entry)
|
| 865 |
+
else:
|
| 866 |
+
self._visit(arg)
|
| 867 |
+
return node
|
| 868 |
+
|
| 869 |
+
def visit_CArgDeclNode(self, node):
|
| 870 |
+
entry = self.env.lookup(node.name)
|
| 871 |
+
if entry:
|
| 872 |
+
may_be_none = not node.not_none
|
| 873 |
+
self.flow.mark_argument(
|
| 874 |
+
node, TypedExprNode(entry.type, may_be_none), entry)
|
| 875 |
+
return node
|
| 876 |
+
|
| 877 |
+
def visit_NameNode(self, node):
|
| 878 |
+
if self.flow.block:
|
| 879 |
+
entry = node.entry or self.env.lookup(node.name)
|
| 880 |
+
if entry:
|
| 881 |
+
self.flow.mark_reference(node, entry)
|
| 882 |
+
|
| 883 |
+
if entry in self.reductions and not self.in_inplace_assignment:
|
| 884 |
+
error(node.pos,
|
| 885 |
+
"Cannot read reduction variable in loop body")
|
| 886 |
+
|
| 887 |
+
return node
|
| 888 |
+
|
| 889 |
+
def visit_StatListNode(self, node):
|
| 890 |
+
if self.flow.block:
|
| 891 |
+
for stat in node.stats:
|
| 892 |
+
self._visit(stat)
|
| 893 |
+
if not self.flow.block:
|
| 894 |
+
stat.is_terminator = True
|
| 895 |
+
break
|
| 896 |
+
return node
|
| 897 |
+
|
| 898 |
+
def visit_Node(self, node):
|
| 899 |
+
self.visitchildren(node)
|
| 900 |
+
self.mark_position(node)
|
| 901 |
+
return node
|
| 902 |
+
|
| 903 |
+
def visit_SizeofVarNode(self, node):
|
| 904 |
+
return node
|
| 905 |
+
|
| 906 |
+
def visit_TypeidNode(self, node):
|
| 907 |
+
return node
|
| 908 |
+
|
| 909 |
+
def visit_IfStatNode(self, node):
|
| 910 |
+
next_block = self.flow.newblock()
|
| 911 |
+
parent = self.flow.block
|
| 912 |
+
# If clauses
|
| 913 |
+
for clause in node.if_clauses:
|
| 914 |
+
parent = self.flow.nextblock(parent)
|
| 915 |
+
self._visit(clause.condition)
|
| 916 |
+
self.flow.nextblock()
|
| 917 |
+
self._visit(clause.body)
|
| 918 |
+
if self.flow.block:
|
| 919 |
+
self.flow.block.add_child(next_block)
|
| 920 |
+
# Else clause
|
| 921 |
+
if node.else_clause:
|
| 922 |
+
self.flow.nextblock(parent=parent)
|
| 923 |
+
self._visit(node.else_clause)
|
| 924 |
+
if self.flow.block:
|
| 925 |
+
self.flow.block.add_child(next_block)
|
| 926 |
+
else:
|
| 927 |
+
parent.add_child(next_block)
|
| 928 |
+
|
| 929 |
+
if next_block.parents:
|
| 930 |
+
self.flow.block = next_block
|
| 931 |
+
else:
|
| 932 |
+
self.flow.block = None
|
| 933 |
+
return node
|
| 934 |
+
|
| 935 |
+
def visit_AssertStatNode(self, node):
|
| 936 |
+
"""Essentially an if-condition that wraps a RaiseStatNode.
|
| 937 |
+
"""
|
| 938 |
+
self.mark_position(node)
|
| 939 |
+
next_block = self.flow.newblock()
|
| 940 |
+
parent = self.flow.block
|
| 941 |
+
# failure case
|
| 942 |
+
parent = self.flow.nextblock(parent)
|
| 943 |
+
self._visit(node.condition)
|
| 944 |
+
self.flow.nextblock()
|
| 945 |
+
self._visit(node.exception)
|
| 946 |
+
if self.flow.block:
|
| 947 |
+
self.flow.block.add_child(next_block)
|
| 948 |
+
parent.add_child(next_block)
|
| 949 |
+
if next_block.parents:
|
| 950 |
+
self.flow.block = next_block
|
| 951 |
+
else:
|
| 952 |
+
self.flow.block = None
|
| 953 |
+
return node
|
| 954 |
+
|
| 955 |
+
def visit_WhileStatNode(self, node):
|
| 956 |
+
condition_block = self.flow.nextblock()
|
| 957 |
+
next_block = self.flow.newblock()
|
| 958 |
+
# Condition block
|
| 959 |
+
self.flow.loops.append(LoopDescr(next_block, condition_block))
|
| 960 |
+
if node.condition:
|
| 961 |
+
self._visit(node.condition)
|
| 962 |
+
# Body block
|
| 963 |
+
self.flow.nextblock()
|
| 964 |
+
self._visit(node.body)
|
| 965 |
+
self.flow.loops.pop()
|
| 966 |
+
# Loop it
|
| 967 |
+
if self.flow.block:
|
| 968 |
+
self.flow.block.add_child(condition_block)
|
| 969 |
+
self.flow.block.add_child(next_block)
|
| 970 |
+
# Else clause
|
| 971 |
+
if node.else_clause:
|
| 972 |
+
self.flow.nextblock(parent=condition_block)
|
| 973 |
+
self._visit(node.else_clause)
|
| 974 |
+
if self.flow.block:
|
| 975 |
+
self.flow.block.add_child(next_block)
|
| 976 |
+
else:
|
| 977 |
+
condition_block.add_child(next_block)
|
| 978 |
+
|
| 979 |
+
if next_block.parents:
|
| 980 |
+
self.flow.block = next_block
|
| 981 |
+
else:
|
| 982 |
+
self.flow.block = None
|
| 983 |
+
return node
|
| 984 |
+
|
| 985 |
+
def mark_forloop_target(self, node):
|
| 986 |
+
# TODO: Remove redundancy with range optimization...
|
| 987 |
+
is_special = False
|
| 988 |
+
sequence = node.iterator.sequence
|
| 989 |
+
target = node.target
|
| 990 |
+
env = node.iterator.expr_scope or self.env
|
| 991 |
+
if isinstance(sequence, ExprNodes.SimpleCallNode):
|
| 992 |
+
function = sequence.function
|
| 993 |
+
if sequence.self is None and function.is_name:
|
| 994 |
+
entry = env.lookup(function.name)
|
| 995 |
+
if not entry or entry.is_builtin:
|
| 996 |
+
if function.name == 'reversed' and len(sequence.args) == 1:
|
| 997 |
+
sequence = sequence.args[0]
|
| 998 |
+
elif function.name == 'enumerate' and len(sequence.args) == 1:
|
| 999 |
+
if target.is_sequence_constructor and len(target.args) == 2:
|
| 1000 |
+
iterator = sequence.args[0]
|
| 1001 |
+
if iterator.is_name:
|
| 1002 |
+
iterator_type = iterator.infer_type(env)
|
| 1003 |
+
if iterator_type.is_builtin_type:
|
| 1004 |
+
# assume that builtin types have a length within Py_ssize_t
|
| 1005 |
+
self.mark_assignment(
|
| 1006 |
+
target.args[0],
|
| 1007 |
+
ExprNodes.IntNode(target.pos, value='PY_SSIZE_T_MAX',
|
| 1008 |
+
type=PyrexTypes.c_py_ssize_t_type),
|
| 1009 |
+
rhs_scope=node.iterator.expr_scope)
|
| 1010 |
+
target = target.args[1]
|
| 1011 |
+
sequence = sequence.args[0]
|
| 1012 |
+
if isinstance(sequence, ExprNodes.SimpleCallNode):
|
| 1013 |
+
function = sequence.function
|
| 1014 |
+
if sequence.self is None and function.is_name:
|
| 1015 |
+
entry = env.lookup(function.name)
|
| 1016 |
+
if not entry or entry.is_builtin:
|
| 1017 |
+
if function.name in ('range', 'xrange'):
|
| 1018 |
+
is_special = True
|
| 1019 |
+
for arg in sequence.args[:2]:
|
| 1020 |
+
self.mark_assignment(target, arg, rhs_scope=node.iterator.expr_scope)
|
| 1021 |
+
if len(sequence.args) > 2:
|
| 1022 |
+
self.mark_assignment(target, self.constant_folder(
|
| 1023 |
+
ExprNodes.binop_node(node.pos,
|
| 1024 |
+
'+',
|
| 1025 |
+
sequence.args[0],
|
| 1026 |
+
sequence.args[2])),
|
| 1027 |
+
rhs_scope=node.iterator.expr_scope)
|
| 1028 |
+
|
| 1029 |
+
if not is_special:
|
| 1030 |
+
# A for-loop basically translates to subsequent calls to
|
| 1031 |
+
# __getitem__(), so using an IndexNode here allows us to
|
| 1032 |
+
# naturally infer the base type of pointers, C arrays,
|
| 1033 |
+
# Python strings, etc., while correctly falling back to an
|
| 1034 |
+
# object type when the base type cannot be handled.
|
| 1035 |
+
|
| 1036 |
+
self.mark_assignment(target, node.item, rhs_scope=node.iterator.expr_scope)
|
| 1037 |
+
|
| 1038 |
+
def visit_AsyncForStatNode(self, node):
|
| 1039 |
+
return self.visit_ForInStatNode(node)
|
| 1040 |
+
|
| 1041 |
+
def visit_ForInStatNode(self, node):
|
| 1042 |
+
condition_block = self.flow.nextblock()
|
| 1043 |
+
next_block = self.flow.newblock()
|
| 1044 |
+
# Condition with iterator
|
| 1045 |
+
self.flow.loops.append(LoopDescr(next_block, condition_block))
|
| 1046 |
+
self._visit(node.iterator)
|
| 1047 |
+
# Target assignment
|
| 1048 |
+
self.flow.nextblock()
|
| 1049 |
+
|
| 1050 |
+
if isinstance(node, Nodes.ForInStatNode):
|
| 1051 |
+
self.mark_forloop_target(node)
|
| 1052 |
+
elif isinstance(node, Nodes.AsyncForStatNode):
|
| 1053 |
+
# not entirely correct, but good enough for now
|
| 1054 |
+
self.mark_assignment(node.target, node.item)
|
| 1055 |
+
else: # Parallel
|
| 1056 |
+
self.mark_assignment(node.target)
|
| 1057 |
+
|
| 1058 |
+
# Body block
|
| 1059 |
+
if isinstance(node, Nodes.ParallelRangeNode):
|
| 1060 |
+
# In case of an invalid
|
| 1061 |
+
self._delete_privates(node, exclude=node.target.entry)
|
| 1062 |
+
|
| 1063 |
+
self.flow.nextblock()
|
| 1064 |
+
self._visit(node.body)
|
| 1065 |
+
self.flow.loops.pop()
|
| 1066 |
+
|
| 1067 |
+
# Loop it
|
| 1068 |
+
if self.flow.block:
|
| 1069 |
+
self.flow.block.add_child(condition_block)
|
| 1070 |
+
# Else clause
|
| 1071 |
+
if node.else_clause:
|
| 1072 |
+
self.flow.nextblock(parent=condition_block)
|
| 1073 |
+
self._visit(node.else_clause)
|
| 1074 |
+
if self.flow.block:
|
| 1075 |
+
self.flow.block.add_child(next_block)
|
| 1076 |
+
else:
|
| 1077 |
+
condition_block.add_child(next_block)
|
| 1078 |
+
|
| 1079 |
+
if next_block.parents:
|
| 1080 |
+
self.flow.block = next_block
|
| 1081 |
+
else:
|
| 1082 |
+
self.flow.block = None
|
| 1083 |
+
return node
|
| 1084 |
+
|
| 1085 |
+
def _delete_privates(self, node, exclude=None):
|
| 1086 |
+
for private_node in node.assigned_nodes:
|
| 1087 |
+
if not exclude or private_node.entry is not exclude:
|
| 1088 |
+
self.flow.mark_deletion(private_node, private_node.entry)
|
| 1089 |
+
|
| 1090 |
+
def visit_ParallelRangeNode(self, node):
|
| 1091 |
+
reductions = self.reductions
|
| 1092 |
+
|
| 1093 |
+
# if node.target is None or not a NameNode, an error will have
|
| 1094 |
+
# been previously issued
|
| 1095 |
+
if hasattr(node.target, 'entry'):
|
| 1096 |
+
self.reductions = set(reductions)
|
| 1097 |
+
|
| 1098 |
+
for private_node in node.assigned_nodes:
|
| 1099 |
+
private_node.entry.error_on_uninitialized = True
|
| 1100 |
+
pos, reduction = node.assignments[private_node.entry]
|
| 1101 |
+
if reduction:
|
| 1102 |
+
self.reductions.add(private_node.entry)
|
| 1103 |
+
|
| 1104 |
+
node = self.visit_ForInStatNode(node)
|
| 1105 |
+
|
| 1106 |
+
self.reductions = reductions
|
| 1107 |
+
return node
|
| 1108 |
+
|
| 1109 |
+
def visit_ParallelWithBlockNode(self, node):
|
| 1110 |
+
for private_node in node.assigned_nodes:
|
| 1111 |
+
private_node.entry.error_on_uninitialized = True
|
| 1112 |
+
|
| 1113 |
+
self._delete_privates(node)
|
| 1114 |
+
self.visitchildren(node)
|
| 1115 |
+
self._delete_privates(node)
|
| 1116 |
+
|
| 1117 |
+
return node
|
| 1118 |
+
|
| 1119 |
+
def visit_ForFromStatNode(self, node):
|
| 1120 |
+
condition_block = self.flow.nextblock()
|
| 1121 |
+
next_block = self.flow.newblock()
|
| 1122 |
+
# Condition with iterator
|
| 1123 |
+
self.flow.loops.append(LoopDescr(next_block, condition_block))
|
| 1124 |
+
self._visit(node.bound1)
|
| 1125 |
+
self._visit(node.bound2)
|
| 1126 |
+
if node.step is not None:
|
| 1127 |
+
self._visit(node.step)
|
| 1128 |
+
# Target assignment
|
| 1129 |
+
self.flow.nextblock()
|
| 1130 |
+
self.mark_assignment(node.target, node.bound1)
|
| 1131 |
+
if node.step is not None:
|
| 1132 |
+
self.mark_assignment(node.target, self.constant_folder(
|
| 1133 |
+
ExprNodes.binop_node(node.pos, '+', node.bound1, node.step)))
|
| 1134 |
+
# Body block
|
| 1135 |
+
self.flow.nextblock()
|
| 1136 |
+
self._visit(node.body)
|
| 1137 |
+
self.flow.loops.pop()
|
| 1138 |
+
# Loop it
|
| 1139 |
+
if self.flow.block:
|
| 1140 |
+
self.flow.block.add_child(condition_block)
|
| 1141 |
+
# Else clause
|
| 1142 |
+
if node.else_clause:
|
| 1143 |
+
self.flow.nextblock(parent=condition_block)
|
| 1144 |
+
self._visit(node.else_clause)
|
| 1145 |
+
if self.flow.block:
|
| 1146 |
+
self.flow.block.add_child(next_block)
|
| 1147 |
+
else:
|
| 1148 |
+
condition_block.add_child(next_block)
|
| 1149 |
+
|
| 1150 |
+
if next_block.parents:
|
| 1151 |
+
self.flow.block = next_block
|
| 1152 |
+
else:
|
| 1153 |
+
self.flow.block = None
|
| 1154 |
+
return node
|
| 1155 |
+
|
| 1156 |
+
def visit_LoopNode(self, node):
|
| 1157 |
+
raise InternalError("Generic loops are not supported")
|
| 1158 |
+
|
| 1159 |
+
def visit_WithTargetAssignmentStatNode(self, node):
|
| 1160 |
+
self.mark_assignment(node.lhs, node.with_node.enter_call)
|
| 1161 |
+
return node
|
| 1162 |
+
|
| 1163 |
+
def visit_WithStatNode(self, node):
|
| 1164 |
+
self._visit(node.manager)
|
| 1165 |
+
self._visit(node.enter_call)
|
| 1166 |
+
self._visit(node.body)
|
| 1167 |
+
return node
|
| 1168 |
+
|
| 1169 |
+
def visit_TryExceptStatNode(self, node):
|
| 1170 |
+
# After exception handling
|
| 1171 |
+
next_block = self.flow.newblock()
|
| 1172 |
+
# Body block
|
| 1173 |
+
self.flow.newblock()
|
| 1174 |
+
# Exception entry point
|
| 1175 |
+
entry_point = self.flow.newblock()
|
| 1176 |
+
self.flow.exceptions.append(ExceptionDescr(entry_point))
|
| 1177 |
+
self.flow.nextblock()
|
| 1178 |
+
## XXX: links to exception handling point should be added by
|
| 1179 |
+
## XXX: children nodes
|
| 1180 |
+
self.flow.block.add_child(entry_point)
|
| 1181 |
+
self.flow.nextblock()
|
| 1182 |
+
self.flow.in_try_block += 1
|
| 1183 |
+
self._visit(node.body)
|
| 1184 |
+
self.flow.in_try_block -= 1
|
| 1185 |
+
self.flow.exceptions.pop()
|
| 1186 |
+
|
| 1187 |
+
# After exception
|
| 1188 |
+
if self.flow.block:
|
| 1189 |
+
if node.else_clause:
|
| 1190 |
+
self.flow.nextblock()
|
| 1191 |
+
self._visit(node.else_clause)
|
| 1192 |
+
if self.flow.block:
|
| 1193 |
+
self.flow.block.add_child(next_block)
|
| 1194 |
+
|
| 1195 |
+
for clause in node.except_clauses:
|
| 1196 |
+
self.flow.block = entry_point
|
| 1197 |
+
if clause.pattern:
|
| 1198 |
+
for pattern in clause.pattern:
|
| 1199 |
+
self._visit(pattern)
|
| 1200 |
+
else:
|
| 1201 |
+
# TODO: handle * pattern
|
| 1202 |
+
pass
|
| 1203 |
+
entry_point = self.flow.newblock(parent=self.flow.block)
|
| 1204 |
+
self.flow.nextblock()
|
| 1205 |
+
if clause.target:
|
| 1206 |
+
self.mark_assignment(clause.target)
|
| 1207 |
+
self._visit(clause.body)
|
| 1208 |
+
if self.flow.block:
|
| 1209 |
+
self.flow.block.add_child(next_block)
|
| 1210 |
+
|
| 1211 |
+
if self.flow.exceptions:
|
| 1212 |
+
entry_point.add_child(self.flow.exceptions[-1].entry_point)
|
| 1213 |
+
|
| 1214 |
+
if next_block.parents:
|
| 1215 |
+
self.flow.block = next_block
|
| 1216 |
+
else:
|
| 1217 |
+
self.flow.block = None
|
| 1218 |
+
return node
|
| 1219 |
+
|
| 1220 |
+
def visit_TryFinallyStatNode(self, node):
|
| 1221 |
+
body_block = self.flow.nextblock()
|
| 1222 |
+
|
| 1223 |
+
# Exception entry point
|
| 1224 |
+
entry_point = self.flow.newblock()
|
| 1225 |
+
self.flow.block = entry_point
|
| 1226 |
+
self._visit(node.finally_except_clause)
|
| 1227 |
+
|
| 1228 |
+
if self.flow.block and self.flow.exceptions:
|
| 1229 |
+
self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
|
| 1230 |
+
|
| 1231 |
+
# Normal execution
|
| 1232 |
+
finally_enter = self.flow.newblock()
|
| 1233 |
+
self.flow.block = finally_enter
|
| 1234 |
+
self._visit(node.finally_clause)
|
| 1235 |
+
finally_exit = self.flow.block
|
| 1236 |
+
|
| 1237 |
+
descr = ExceptionDescr(entry_point, finally_enter, finally_exit)
|
| 1238 |
+
self.flow.exceptions.append(descr)
|
| 1239 |
+
if self.flow.loops:
|
| 1240 |
+
self.flow.loops[-1].exceptions.append(descr)
|
| 1241 |
+
self.flow.block = body_block
|
| 1242 |
+
body_block.add_child(entry_point)
|
| 1243 |
+
self.flow.nextblock()
|
| 1244 |
+
self.flow.in_try_block += 1
|
| 1245 |
+
self._visit(node.body)
|
| 1246 |
+
self.flow.in_try_block -= 1
|
| 1247 |
+
self.flow.exceptions.pop()
|
| 1248 |
+
if self.flow.loops:
|
| 1249 |
+
self.flow.loops[-1].exceptions.pop()
|
| 1250 |
+
|
| 1251 |
+
if self.flow.block:
|
| 1252 |
+
self.flow.block.add_child(finally_enter)
|
| 1253 |
+
if finally_exit:
|
| 1254 |
+
self.flow.block = self.flow.nextblock(parent=finally_exit)
|
| 1255 |
+
else:
|
| 1256 |
+
self.flow.block = None
|
| 1257 |
+
return node
|
| 1258 |
+
|
| 1259 |
+
def visit_RaiseStatNode(self, node):
|
| 1260 |
+
self.mark_position(node)
|
| 1261 |
+
self.visitchildren(node)
|
| 1262 |
+
if self.flow.exceptions:
|
| 1263 |
+
self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
|
| 1264 |
+
self.flow.block = None
|
| 1265 |
+
if self.flow.in_try_block:
|
| 1266 |
+
node.in_try_block = True
|
| 1267 |
+
return node
|
| 1268 |
+
|
| 1269 |
+
def visit_ReraiseStatNode(self, node):
|
| 1270 |
+
self.mark_position(node)
|
| 1271 |
+
if self.flow.exceptions:
|
| 1272 |
+
self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
|
| 1273 |
+
self.flow.block = None
|
| 1274 |
+
return node
|
| 1275 |
+
|
| 1276 |
+
def visit_ReturnStatNode(self, node):
|
| 1277 |
+
self.mark_position(node)
|
| 1278 |
+
self.visitchildren(node)
|
| 1279 |
+
|
| 1280 |
+
outer_exception_handlers = iter(self.flow.exceptions[::-1])
|
| 1281 |
+
for handler in outer_exception_handlers:
|
| 1282 |
+
if handler.finally_enter:
|
| 1283 |
+
self.flow.block.add_child(handler.finally_enter)
|
| 1284 |
+
if handler.finally_exit:
|
| 1285 |
+
# 'return' goes to function exit, or to the next outer 'finally' clause
|
| 1286 |
+
exit_point = self.flow.exit_point
|
| 1287 |
+
for next_handler in outer_exception_handlers:
|
| 1288 |
+
if next_handler.finally_enter:
|
| 1289 |
+
exit_point = next_handler.finally_enter
|
| 1290 |
+
break
|
| 1291 |
+
handler.finally_exit.add_child(exit_point)
|
| 1292 |
+
break
|
| 1293 |
+
else:
|
| 1294 |
+
if self.flow.block:
|
| 1295 |
+
self.flow.block.add_child(self.flow.exit_point)
|
| 1296 |
+
self.flow.block = None
|
| 1297 |
+
return node
|
| 1298 |
+
|
| 1299 |
+
def visit_BreakStatNode(self, node):
|
| 1300 |
+
if not self.flow.loops:
|
| 1301 |
+
#error(node.pos, "break statement not inside loop")
|
| 1302 |
+
return node
|
| 1303 |
+
loop = self.flow.loops[-1]
|
| 1304 |
+
self.mark_position(node)
|
| 1305 |
+
for exception in loop.exceptions[::-1]:
|
| 1306 |
+
if exception.finally_enter:
|
| 1307 |
+
self.flow.block.add_child(exception.finally_enter)
|
| 1308 |
+
if exception.finally_exit:
|
| 1309 |
+
exception.finally_exit.add_child(loop.next_block)
|
| 1310 |
+
break
|
| 1311 |
+
else:
|
| 1312 |
+
self.flow.block.add_child(loop.next_block)
|
| 1313 |
+
self.flow.block = None
|
| 1314 |
+
return node
|
| 1315 |
+
|
| 1316 |
+
def visit_ContinueStatNode(self, node):
|
| 1317 |
+
if not self.flow.loops:
|
| 1318 |
+
#error(node.pos, "continue statement not inside loop")
|
| 1319 |
+
return node
|
| 1320 |
+
loop = self.flow.loops[-1]
|
| 1321 |
+
self.mark_position(node)
|
| 1322 |
+
for exception in loop.exceptions[::-1]:
|
| 1323 |
+
if exception.finally_enter:
|
| 1324 |
+
self.flow.block.add_child(exception.finally_enter)
|
| 1325 |
+
if exception.finally_exit:
|
| 1326 |
+
exception.finally_exit.add_child(loop.loop_block)
|
| 1327 |
+
break
|
| 1328 |
+
else:
|
| 1329 |
+
self.flow.block.add_child(loop.loop_block)
|
| 1330 |
+
self.flow.block = None
|
| 1331 |
+
return node
|
| 1332 |
+
|
| 1333 |
+
def visit_ComprehensionNode(self, node):
|
| 1334 |
+
if node.expr_scope:
|
| 1335 |
+
self.stack.append((self.env, self.flow))
|
| 1336 |
+
self.env = node.expr_scope
|
| 1337 |
+
# Skip append node here
|
| 1338 |
+
self._visit(node.loop)
|
| 1339 |
+
if node.expr_scope:
|
| 1340 |
+
self.env, _ = self.stack.pop()
|
| 1341 |
+
return node
|
| 1342 |
+
|
| 1343 |
+
def visit_ScopedExprNode(self, node):
|
| 1344 |
+
# currently this is written to deal with these two types
|
| 1345 |
+
# (with comprehensions covered in their own function)
|
| 1346 |
+
assert isinstance(node, (ExprNodes.IteratorNode, ExprNodes.AsyncIteratorNode)), node
|
| 1347 |
+
if node.expr_scope:
|
| 1348 |
+
self.stack.append((self.env, self.flow))
|
| 1349 |
+
self.flow = self.find_in_stack(node.expr_scope)
|
| 1350 |
+
self.env = node.expr_scope
|
| 1351 |
+
self.visitchildren(node)
|
| 1352 |
+
if node.expr_scope:
|
| 1353 |
+
self.env, self.flow = self.stack.pop()
|
| 1354 |
+
return node
|
| 1355 |
+
|
| 1356 |
+
def visit_PyClassDefNode(self, node):
|
| 1357 |
+
self.visitchildren(node, ('dict', 'metaclass',
|
| 1358 |
+
'mkw', 'bases', 'class_result'))
|
| 1359 |
+
self.flow.mark_assignment(node.target, node.classobj,
|
| 1360 |
+
self.env.lookup(node.target.name))
|
| 1361 |
+
self.stack.append((self.env, self.flow))
|
| 1362 |
+
self.env = node.scope
|
| 1363 |
+
self.flow.nextblock()
|
| 1364 |
+
if node.doc_node:
|
| 1365 |
+
self.flow.mark_assignment(node.doc_node, fake_rhs_expr, node.doc_node.entry)
|
| 1366 |
+
self.visitchildren(node, ('body',))
|
| 1367 |
+
self.flow.nextblock()
|
| 1368 |
+
self.env, _ = self.stack.pop()
|
| 1369 |
+
return node
|
| 1370 |
+
|
| 1371 |
+
def visit_CClassDefNode(self, node):
|
| 1372 |
+
# just make sure the nodes scope is findable in-case there is a list comprehension in it
|
| 1373 |
+
self.stack.append((node.scope, self.flow))
|
| 1374 |
+
self.visitchildren(node)
|
| 1375 |
+
self.stack.pop()
|
| 1376 |
+
return node
|
| 1377 |
+
|
| 1378 |
+
def visit_AmpersandNode(self, node):
|
| 1379 |
+
if node.operand.is_name:
|
| 1380 |
+
# Fake assignment to silence warning
|
| 1381 |
+
self.mark_assignment(node.operand, fake_rhs_expr)
|
| 1382 |
+
self.visitchildren(node)
|
| 1383 |
+
return node
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Main.py
ADDED
|
@@ -0,0 +1,789 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Cython Top Level
|
| 3 |
+
#
|
| 4 |
+
|
| 5 |
+
from __future__ import absolute_import, print_function
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
import re
|
| 9 |
+
import sys
|
| 10 |
+
import io
|
| 11 |
+
|
| 12 |
+
if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 3):
|
| 13 |
+
sys.stderr.write("Sorry, Cython requires Python 2.7 or 3.3+, found %d.%d\n" % tuple(sys.version_info[:2]))
|
| 14 |
+
sys.exit(1)
|
| 15 |
+
|
| 16 |
+
try:
|
| 17 |
+
from __builtin__ import basestring
|
| 18 |
+
except ImportError:
|
| 19 |
+
basestring = str
|
| 20 |
+
|
| 21 |
+
# Do not import Parsing here, import it when needed, because Parsing imports
|
| 22 |
+
# Nodes, which globally needs debug command line options initialized to set a
|
| 23 |
+
# conditional metaclass. These options are processed by CmdLine called from
|
| 24 |
+
# main() in this file.
|
| 25 |
+
# import Parsing
|
| 26 |
+
from . import Errors
|
| 27 |
+
from .StringEncoding import EncodedString
|
| 28 |
+
from .Scanning import PyrexScanner, FileSourceDescriptor
|
| 29 |
+
from .Errors import PyrexError, CompileError, error, warning
|
| 30 |
+
from .Symtab import ModuleScope
|
| 31 |
+
from .. import Utils
|
| 32 |
+
from . import Options
|
| 33 |
+
from .Options import CompilationOptions, default_options
|
| 34 |
+
from .CmdLine import parse_command_line
|
| 35 |
+
from .Lexicon import (unicode_start_ch_any, unicode_continuation_ch_any,
|
| 36 |
+
unicode_start_ch_range, unicode_continuation_ch_range)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _make_range_re(chrs):
|
| 40 |
+
out = []
|
| 41 |
+
for i in range(0, len(chrs), 2):
|
| 42 |
+
out.append(u"{0}-{1}".format(chrs[i], chrs[i+1]))
|
| 43 |
+
return u"".join(out)
|
| 44 |
+
|
| 45 |
+
# py2 version looked like r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$"
|
| 46 |
+
module_name_pattern = u"[{0}{1}][{0}{2}{1}{3}]*".format(
|
| 47 |
+
unicode_start_ch_any, _make_range_re(unicode_start_ch_range),
|
| 48 |
+
unicode_continuation_ch_any,
|
| 49 |
+
_make_range_re(unicode_continuation_ch_range))
|
| 50 |
+
module_name_pattern = re.compile(u"{0}(\\.{0})*$".format(module_name_pattern))
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
standard_include_path = os.path.abspath(
|
| 54 |
+
os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Includes'))
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class Context(object):
|
| 58 |
+
# This class encapsulates the context needed for compiling
|
| 59 |
+
# one or more Cython implementation files along with their
|
| 60 |
+
# associated and imported declaration files. It includes
|
| 61 |
+
# the root of the module import namespace and the list
|
| 62 |
+
# of directories to search for include files.
|
| 63 |
+
#
|
| 64 |
+
# modules {string : ModuleScope}
|
| 65 |
+
# include_directories [string]
|
| 66 |
+
# future_directives [object]
|
| 67 |
+
# language_level int currently 2 or 3 for Python 2/3
|
| 68 |
+
|
| 69 |
+
cython_scope = None
|
| 70 |
+
language_level = None # warn when not set but default to Py2
|
| 71 |
+
|
| 72 |
+
def __init__(self, include_directories, compiler_directives, cpp=False,
|
| 73 |
+
language_level=None, options=None):
|
| 74 |
+
# cython_scope is a hack, set to False by subclasses, in order to break
|
| 75 |
+
# an infinite loop.
|
| 76 |
+
# Better code organization would fix it.
|
| 77 |
+
|
| 78 |
+
from . import Builtin, CythonScope
|
| 79 |
+
self.modules = {"__builtin__" : Builtin.builtin_scope}
|
| 80 |
+
self.cython_scope = CythonScope.create_cython_scope(self)
|
| 81 |
+
self.modules["cython"] = self.cython_scope
|
| 82 |
+
self.include_directories = include_directories
|
| 83 |
+
self.future_directives = set()
|
| 84 |
+
self.compiler_directives = compiler_directives
|
| 85 |
+
self.cpp = cpp
|
| 86 |
+
self.options = options
|
| 87 |
+
|
| 88 |
+
self.pxds = {} # full name -> node tree
|
| 89 |
+
self._interned = {} # (type(value), value, *key_args) -> interned_value
|
| 90 |
+
|
| 91 |
+
if language_level is not None:
|
| 92 |
+
self.set_language_level(language_level)
|
| 93 |
+
|
| 94 |
+
self.legacy_implicit_noexcept = self.compiler_directives.get('legacy_implicit_noexcept', False)
|
| 95 |
+
|
| 96 |
+
self.gdb_debug_outputwriter = None
|
| 97 |
+
|
| 98 |
+
@classmethod
|
| 99 |
+
def from_options(cls, options):
|
| 100 |
+
return cls(options.include_path, options.compiler_directives,
|
| 101 |
+
options.cplus, options.language_level, options=options)
|
| 102 |
+
|
| 103 |
+
def set_language_level(self, level):
|
| 104 |
+
from .Future import print_function, unicode_literals, absolute_import, division, generator_stop
|
| 105 |
+
future_directives = set()
|
| 106 |
+
if level == '3str':
|
| 107 |
+
level = 3
|
| 108 |
+
else:
|
| 109 |
+
level = int(level)
|
| 110 |
+
if level >= 3:
|
| 111 |
+
future_directives.add(unicode_literals)
|
| 112 |
+
if level >= 3:
|
| 113 |
+
future_directives.update([print_function, absolute_import, division, generator_stop])
|
| 114 |
+
self.language_level = level
|
| 115 |
+
self.future_directives = future_directives
|
| 116 |
+
if level >= 3:
|
| 117 |
+
self.modules['builtins'] = self.modules['__builtin__']
|
| 118 |
+
|
| 119 |
+
def intern_ustring(self, value, encoding=None):
|
| 120 |
+
key = (EncodedString, value, encoding)
|
| 121 |
+
try:
|
| 122 |
+
return self._interned[key]
|
| 123 |
+
except KeyError:
|
| 124 |
+
pass
|
| 125 |
+
value = EncodedString(value)
|
| 126 |
+
if encoding:
|
| 127 |
+
value.encoding = encoding
|
| 128 |
+
self._interned[key] = value
|
| 129 |
+
return value
|
| 130 |
+
|
| 131 |
+
# pipeline creation functions can now be found in Pipeline.py
|
| 132 |
+
|
| 133 |
+
def process_pxd(self, source_desc, scope, module_name):
|
| 134 |
+
from . import Pipeline
|
| 135 |
+
if isinstance(source_desc, FileSourceDescriptor) and source_desc._file_type == 'pyx':
|
| 136 |
+
source = CompilationSource(source_desc, module_name, os.getcwd())
|
| 137 |
+
result_sink = create_default_resultobj(source, self.options)
|
| 138 |
+
pipeline = Pipeline.create_pyx_as_pxd_pipeline(self, result_sink)
|
| 139 |
+
result = Pipeline.run_pipeline(pipeline, source)
|
| 140 |
+
else:
|
| 141 |
+
pipeline = Pipeline.create_pxd_pipeline(self, scope, module_name)
|
| 142 |
+
result = Pipeline.run_pipeline(pipeline, source_desc)
|
| 143 |
+
return result
|
| 144 |
+
|
| 145 |
+
def nonfatal_error(self, exc):
|
| 146 |
+
return Errors.report_error(exc)
|
| 147 |
+
|
| 148 |
+
def _split_qualified_name(self, qualified_name, relative_import=False):
|
| 149 |
+
# Splits qualified_name into parts in form of 2-tuples: (PART_NAME, IS_PACKAGE).
|
| 150 |
+
qualified_name_parts = qualified_name.split('.')
|
| 151 |
+
last_part = qualified_name_parts.pop()
|
| 152 |
+
qualified_name_parts = [(p, True) for p in qualified_name_parts]
|
| 153 |
+
if last_part != '__init__':
|
| 154 |
+
# If Last part is __init__, then it is omitted. Otherwise, we need to check whether we can find
|
| 155 |
+
# __init__.pyx/__init__.py file to determine if last part is package or not.
|
| 156 |
+
is_package = False
|
| 157 |
+
for suffix in ('.py', '.pyx'):
|
| 158 |
+
path = self.search_include_directories(
|
| 159 |
+
qualified_name, suffix=suffix, source_pos=None, source_file_path=None, sys_path=not relative_import)
|
| 160 |
+
if path:
|
| 161 |
+
is_package = self._is_init_file(path)
|
| 162 |
+
break
|
| 163 |
+
|
| 164 |
+
qualified_name_parts.append((last_part, is_package))
|
| 165 |
+
return qualified_name_parts
|
| 166 |
+
|
| 167 |
+
@staticmethod
|
| 168 |
+
def _is_init_file(path):
|
| 169 |
+
return os.path.basename(path) in ('__init__.pyx', '__init__.py', '__init__.pxd') if path else False
|
| 170 |
+
|
| 171 |
+
@staticmethod
|
| 172 |
+
def _check_pxd_filename(pos, pxd_pathname, qualified_name):
|
| 173 |
+
if not pxd_pathname:
|
| 174 |
+
return
|
| 175 |
+
pxd_filename = os.path.basename(pxd_pathname)
|
| 176 |
+
if '.' in qualified_name and qualified_name == os.path.splitext(pxd_filename)[0]:
|
| 177 |
+
warning(pos, "Dotted filenames ('%s') are deprecated."
|
| 178 |
+
" Please use the normal Python package directory layout." % pxd_filename, level=1)
|
| 179 |
+
|
| 180 |
+
def find_module(self, module_name, from_module=None, pos=None, need_pxd=1,
|
| 181 |
+
absolute_fallback=True, relative_import=False):
|
| 182 |
+
# Finds and returns the module scope corresponding to
|
| 183 |
+
# the given relative or absolute module name. If this
|
| 184 |
+
# is the first time the module has been requested, finds
|
| 185 |
+
# the corresponding .pxd file and process it.
|
| 186 |
+
# If from_module is not None, it must be a module scope,
|
| 187 |
+
# and the module will first be searched for relative to
|
| 188 |
+
# that module, provided its name is not a dotted name.
|
| 189 |
+
debug_find_module = 0
|
| 190 |
+
if debug_find_module:
|
| 191 |
+
print("Context.find_module: module_name = %s, from_module = %s, pos = %s, need_pxd = %s" % (
|
| 192 |
+
module_name, from_module, pos, need_pxd))
|
| 193 |
+
|
| 194 |
+
scope = None
|
| 195 |
+
pxd_pathname = None
|
| 196 |
+
if from_module:
|
| 197 |
+
if module_name:
|
| 198 |
+
# from .module import ...
|
| 199 |
+
qualified_name = from_module.qualify_name(module_name)
|
| 200 |
+
else:
|
| 201 |
+
# from . import ...
|
| 202 |
+
qualified_name = from_module.qualified_name
|
| 203 |
+
scope = from_module
|
| 204 |
+
from_module = None
|
| 205 |
+
else:
|
| 206 |
+
qualified_name = module_name
|
| 207 |
+
|
| 208 |
+
if not module_name_pattern.match(qualified_name):
|
| 209 |
+
raise CompileError(pos or (module_name, 0, 0),
|
| 210 |
+
u"'%s' is not a valid module name" % module_name)
|
| 211 |
+
|
| 212 |
+
if from_module:
|
| 213 |
+
if debug_find_module:
|
| 214 |
+
print("...trying relative import")
|
| 215 |
+
scope = from_module.lookup_submodule(module_name)
|
| 216 |
+
if not scope:
|
| 217 |
+
pxd_pathname = self.find_pxd_file(qualified_name, pos, sys_path=not relative_import)
|
| 218 |
+
self._check_pxd_filename(pos, pxd_pathname, qualified_name)
|
| 219 |
+
if pxd_pathname:
|
| 220 |
+
is_package = self._is_init_file(pxd_pathname)
|
| 221 |
+
scope = from_module.find_submodule(module_name, as_package=is_package)
|
| 222 |
+
if not scope:
|
| 223 |
+
if debug_find_module:
|
| 224 |
+
print("...trying absolute import")
|
| 225 |
+
if absolute_fallback:
|
| 226 |
+
qualified_name = module_name
|
| 227 |
+
scope = self
|
| 228 |
+
for name, is_package in self._split_qualified_name(qualified_name, relative_import=relative_import):
|
| 229 |
+
scope = scope.find_submodule(name, as_package=is_package)
|
| 230 |
+
if debug_find_module:
|
| 231 |
+
print("...scope = %s" % scope)
|
| 232 |
+
if not scope.pxd_file_loaded:
|
| 233 |
+
if debug_find_module:
|
| 234 |
+
print("...pxd not loaded")
|
| 235 |
+
if not pxd_pathname:
|
| 236 |
+
if debug_find_module:
|
| 237 |
+
print("...looking for pxd file")
|
| 238 |
+
# Only look in sys.path if we are explicitly looking
|
| 239 |
+
# for a .pxd file.
|
| 240 |
+
pxd_pathname = self.find_pxd_file(qualified_name, pos, sys_path=need_pxd and not relative_import)
|
| 241 |
+
self._check_pxd_filename(pos, pxd_pathname, qualified_name)
|
| 242 |
+
if debug_find_module:
|
| 243 |
+
print("......found %s" % pxd_pathname)
|
| 244 |
+
if not pxd_pathname and need_pxd:
|
| 245 |
+
# Set pxd_file_loaded such that we don't need to
|
| 246 |
+
# look for the non-existing pxd file next time.
|
| 247 |
+
scope.pxd_file_loaded = True
|
| 248 |
+
package_pathname = self.search_include_directories(
|
| 249 |
+
qualified_name, suffix=".py", source_pos=pos, sys_path=not relative_import)
|
| 250 |
+
if package_pathname and package_pathname.endswith(Utils.PACKAGE_FILES):
|
| 251 |
+
pass
|
| 252 |
+
else:
|
| 253 |
+
error(pos, "'%s.pxd' not found" % qualified_name.replace('.', os.sep))
|
| 254 |
+
if pxd_pathname:
|
| 255 |
+
scope.pxd_file_loaded = True
|
| 256 |
+
try:
|
| 257 |
+
if debug_find_module:
|
| 258 |
+
print("Context.find_module: Parsing %s" % pxd_pathname)
|
| 259 |
+
rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
|
| 260 |
+
if not pxd_pathname.endswith(rel_path):
|
| 261 |
+
rel_path = pxd_pathname # safety measure to prevent printing incorrect paths
|
| 262 |
+
source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
|
| 263 |
+
err, result = self.process_pxd(source_desc, scope, qualified_name)
|
| 264 |
+
if err:
|
| 265 |
+
raise err
|
| 266 |
+
(pxd_codenodes, pxd_scope) = result
|
| 267 |
+
self.pxds[module_name] = (pxd_codenodes, pxd_scope)
|
| 268 |
+
except CompileError:
|
| 269 |
+
pass
|
| 270 |
+
return scope
|
| 271 |
+
|
| 272 |
+
def find_pxd_file(self, qualified_name, pos=None, sys_path=True, source_file_path=None):
|
| 273 |
+
# Search include path (and sys.path if sys_path is True) for
|
| 274 |
+
# the .pxd file corresponding to the given fully-qualified
|
| 275 |
+
# module name.
|
| 276 |
+
# Will find either a dotted filename or a file in a
|
| 277 |
+
# package directory. If a source file position is given,
|
| 278 |
+
# the directory containing the source file is searched first
|
| 279 |
+
# for a dotted filename, and its containing package root
|
| 280 |
+
# directory is searched first for a non-dotted filename.
|
| 281 |
+
pxd = self.search_include_directories(
|
| 282 |
+
qualified_name, suffix=".pxd", source_pos=pos, sys_path=sys_path, source_file_path=source_file_path)
|
| 283 |
+
if pxd is None and Options.cimport_from_pyx:
|
| 284 |
+
return self.find_pyx_file(qualified_name, pos, sys_path=sys_path)
|
| 285 |
+
return pxd
|
| 286 |
+
|
| 287 |
+
def find_pyx_file(self, qualified_name, pos=None, sys_path=True, source_file_path=None):
|
| 288 |
+
# Search include path for the .pyx file corresponding to the
|
| 289 |
+
# given fully-qualified module name, as for find_pxd_file().
|
| 290 |
+
return self.search_include_directories(
|
| 291 |
+
qualified_name, suffix=".pyx", source_pos=pos, sys_path=sys_path, source_file_path=source_file_path)
|
| 292 |
+
|
| 293 |
+
def find_include_file(self, filename, pos=None, source_file_path=None):
|
| 294 |
+
# Search list of include directories for filename.
|
| 295 |
+
# Reports an error and returns None if not found.
|
| 296 |
+
path = self.search_include_directories(
|
| 297 |
+
filename, source_pos=pos, include=True, source_file_path=source_file_path)
|
| 298 |
+
if not path:
|
| 299 |
+
error(pos, "'%s' not found" % filename)
|
| 300 |
+
return path
|
| 301 |
+
|
| 302 |
+
def search_include_directories(self, qualified_name,
|
| 303 |
+
suffix=None, source_pos=None, include=False, sys_path=False, source_file_path=None):
|
| 304 |
+
include_dirs = self.include_directories
|
| 305 |
+
if sys_path:
|
| 306 |
+
include_dirs = include_dirs + sys.path
|
| 307 |
+
# include_dirs must be hashable for caching in @cached_function
|
| 308 |
+
include_dirs = tuple(include_dirs + [standard_include_path])
|
| 309 |
+
return search_include_directories(
|
| 310 |
+
include_dirs, qualified_name, suffix or "", source_pos, include, source_file_path)
|
| 311 |
+
|
| 312 |
+
def find_root_package_dir(self, file_path):
|
| 313 |
+
return Utils.find_root_package_dir(file_path)
|
| 314 |
+
|
| 315 |
+
def check_package_dir(self, dir, package_names):
|
| 316 |
+
return Utils.check_package_dir(dir, tuple(package_names))
|
| 317 |
+
|
| 318 |
+
def c_file_out_of_date(self, source_path, output_path):
|
| 319 |
+
if not os.path.exists(output_path):
|
| 320 |
+
return 1
|
| 321 |
+
c_time = Utils.modification_time(output_path)
|
| 322 |
+
if Utils.file_newer_than(source_path, c_time):
|
| 323 |
+
return 1
|
| 324 |
+
pxd_path = Utils.replace_suffix(source_path, ".pxd")
|
| 325 |
+
if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time):
|
| 326 |
+
return 1
|
| 327 |
+
for kind, name in self.read_dependency_file(source_path):
|
| 328 |
+
if kind == "cimport":
|
| 329 |
+
dep_path = self.find_pxd_file(name, source_file_path=source_path)
|
| 330 |
+
elif kind == "include":
|
| 331 |
+
dep_path = self.search_include_directories(name, source_file_path=source_path)
|
| 332 |
+
else:
|
| 333 |
+
continue
|
| 334 |
+
if dep_path and Utils.file_newer_than(dep_path, c_time):
|
| 335 |
+
return 1
|
| 336 |
+
return 0
|
| 337 |
+
|
| 338 |
+
def find_cimported_module_names(self, source_path):
|
| 339 |
+
return [ name for kind, name in self.read_dependency_file(source_path)
|
| 340 |
+
if kind == "cimport" ]
|
| 341 |
+
|
| 342 |
+
def is_package_dir(self, dir_path):
|
| 343 |
+
return Utils.is_package_dir(dir_path)
|
| 344 |
+
|
| 345 |
+
def read_dependency_file(self, source_path):
|
| 346 |
+
dep_path = Utils.replace_suffix(source_path, ".dep")
|
| 347 |
+
if os.path.exists(dep_path):
|
| 348 |
+
with open(dep_path, "rU") as f:
|
| 349 |
+
chunks = [ line.split(" ", 1)
|
| 350 |
+
for line in (l.strip() for l in f)
|
| 351 |
+
if " " in line ]
|
| 352 |
+
return chunks
|
| 353 |
+
else:
|
| 354 |
+
return ()
|
| 355 |
+
|
| 356 |
+
def lookup_submodule(self, name):
|
| 357 |
+
# Look up a top-level module. Returns None if not found.
|
| 358 |
+
return self.modules.get(name, None)
|
| 359 |
+
|
| 360 |
+
def find_submodule(self, name, as_package=False):
|
| 361 |
+
# Find a top-level module, creating a new one if needed.
|
| 362 |
+
scope = self.lookup_submodule(name)
|
| 363 |
+
if not scope:
|
| 364 |
+
scope = ModuleScope(name,
|
| 365 |
+
parent_module = None, context = self, is_package=as_package)
|
| 366 |
+
self.modules[name] = scope
|
| 367 |
+
return scope
|
| 368 |
+
|
| 369 |
+
def parse(self, source_desc, scope, pxd, full_module_name):
|
| 370 |
+
if not isinstance(source_desc, FileSourceDescriptor):
|
| 371 |
+
raise RuntimeError("Only file sources for code supported")
|
| 372 |
+
source_filename = source_desc.filename
|
| 373 |
+
scope.cpp = self.cpp
|
| 374 |
+
# Parse the given source file and return a parse tree.
|
| 375 |
+
num_errors = Errors.get_errors_count()
|
| 376 |
+
try:
|
| 377 |
+
with Utils.open_source_file(source_filename) as f:
|
| 378 |
+
from . import Parsing
|
| 379 |
+
s = PyrexScanner(f, source_desc, source_encoding = f.encoding,
|
| 380 |
+
scope = scope, context = self)
|
| 381 |
+
tree = Parsing.p_module(s, pxd, full_module_name)
|
| 382 |
+
if self.options.formal_grammar:
|
| 383 |
+
try:
|
| 384 |
+
from ..Parser import ConcreteSyntaxTree
|
| 385 |
+
except ImportError:
|
| 386 |
+
raise RuntimeError(
|
| 387 |
+
"Formal grammar can only be used with compiled Cython with an available pgen.")
|
| 388 |
+
ConcreteSyntaxTree.p_module(source_filename)
|
| 389 |
+
except UnicodeDecodeError as e:
|
| 390 |
+
#import traceback
|
| 391 |
+
#traceback.print_exc()
|
| 392 |
+
raise self._report_decode_error(source_desc, e)
|
| 393 |
+
|
| 394 |
+
if Errors.get_errors_count() > num_errors:
|
| 395 |
+
raise CompileError()
|
| 396 |
+
return tree
|
| 397 |
+
|
| 398 |
+
def _report_decode_error(self, source_desc, exc):
|
| 399 |
+
msg = exc.args[-1]
|
| 400 |
+
position = exc.args[2]
|
| 401 |
+
encoding = exc.args[0]
|
| 402 |
+
|
| 403 |
+
line = 1
|
| 404 |
+
column = idx = 0
|
| 405 |
+
with io.open(source_desc.filename, "r", encoding='iso8859-1', newline='') as f:
|
| 406 |
+
for line, data in enumerate(f, 1):
|
| 407 |
+
idx += len(data)
|
| 408 |
+
if idx >= position:
|
| 409 |
+
column = position - (idx - len(data)) + 1
|
| 410 |
+
break
|
| 411 |
+
|
| 412 |
+
return error((source_desc, line, column),
|
| 413 |
+
"Decoding error, missing or incorrect coding=<encoding-name> "
|
| 414 |
+
"at top of source (cannot decode with encoding %r: %s)" % (encoding, msg))
|
| 415 |
+
|
| 416 |
+
def extract_module_name(self, path, options):
|
| 417 |
+
# Find fully_qualified module name from the full pathname
|
| 418 |
+
# of a source file.
|
| 419 |
+
dir, filename = os.path.split(path)
|
| 420 |
+
module_name, _ = os.path.splitext(filename)
|
| 421 |
+
if "." in module_name:
|
| 422 |
+
return module_name
|
| 423 |
+
names = [module_name]
|
| 424 |
+
while self.is_package_dir(dir):
|
| 425 |
+
parent, package_name = os.path.split(dir)
|
| 426 |
+
if parent == dir:
|
| 427 |
+
break
|
| 428 |
+
names.append(package_name)
|
| 429 |
+
dir = parent
|
| 430 |
+
names.reverse()
|
| 431 |
+
return ".".join(names)
|
| 432 |
+
|
| 433 |
+
def setup_errors(self, options, result):
|
| 434 |
+
Errors.init_thread()
|
| 435 |
+
if options.use_listing_file:
|
| 436 |
+
path = result.listing_file = Utils.replace_suffix(result.main_source_file, ".lis")
|
| 437 |
+
else:
|
| 438 |
+
path = None
|
| 439 |
+
Errors.open_listing_file(path=path, echo_to_stderr=options.errors_to_stderr)
|
| 440 |
+
|
| 441 |
+
def teardown_errors(self, err, options, result):
|
| 442 |
+
source_desc = result.compilation_source.source_desc
|
| 443 |
+
if not isinstance(source_desc, FileSourceDescriptor):
|
| 444 |
+
raise RuntimeError("Only file sources for code supported")
|
| 445 |
+
Errors.close_listing_file()
|
| 446 |
+
result.num_errors = Errors.get_errors_count()
|
| 447 |
+
if result.num_errors > 0:
|
| 448 |
+
err = True
|
| 449 |
+
if err and result.c_file:
|
| 450 |
+
try:
|
| 451 |
+
Utils.castrate_file(result.c_file, os.stat(source_desc.filename))
|
| 452 |
+
except EnvironmentError:
|
| 453 |
+
pass
|
| 454 |
+
result.c_file = None
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def get_output_filename(source_filename, cwd, options):
|
| 458 |
+
if options.cplus:
|
| 459 |
+
c_suffix = ".cpp"
|
| 460 |
+
else:
|
| 461 |
+
c_suffix = ".c"
|
| 462 |
+
suggested_file_name = Utils.replace_suffix(source_filename, c_suffix)
|
| 463 |
+
if options.output_file:
|
| 464 |
+
out_path = os.path.join(cwd, options.output_file)
|
| 465 |
+
if os.path.isdir(out_path):
|
| 466 |
+
return os.path.join(out_path, os.path.basename(suggested_file_name))
|
| 467 |
+
else:
|
| 468 |
+
return out_path
|
| 469 |
+
else:
|
| 470 |
+
return suggested_file_name
|
| 471 |
+
|
| 472 |
+
|
| 473 |
+
def create_default_resultobj(compilation_source, options):
|
| 474 |
+
result = CompilationResult()
|
| 475 |
+
result.main_source_file = compilation_source.source_desc.filename
|
| 476 |
+
result.compilation_source = compilation_source
|
| 477 |
+
source_desc = compilation_source.source_desc
|
| 478 |
+
result.c_file = get_output_filename(source_desc.filename,
|
| 479 |
+
compilation_source.cwd, options)
|
| 480 |
+
result.embedded_metadata = options.embedded_metadata
|
| 481 |
+
return result
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
def run_pipeline(source, options, full_module_name=None, context=None):
|
| 485 |
+
from . import Pipeline
|
| 486 |
+
|
| 487 |
+
# ensure that the inputs are unicode (for Python 2)
|
| 488 |
+
if sys.version_info[0] == 2:
|
| 489 |
+
source = Utils.decode_filename(source)
|
| 490 |
+
if full_module_name:
|
| 491 |
+
full_module_name = Utils.decode_filename(full_module_name)
|
| 492 |
+
|
| 493 |
+
source_ext = os.path.splitext(source)[1]
|
| 494 |
+
options.configure_language_defaults(source_ext[1:]) # py/pyx
|
| 495 |
+
if context is None:
|
| 496 |
+
context = Context.from_options(options)
|
| 497 |
+
|
| 498 |
+
# Set up source object
|
| 499 |
+
cwd = os.getcwd()
|
| 500 |
+
abs_path = os.path.abspath(source)
|
| 501 |
+
full_module_name = full_module_name or context.extract_module_name(source, options)
|
| 502 |
+
full_module_name = EncodedString(full_module_name)
|
| 503 |
+
|
| 504 |
+
Utils.raise_error_if_module_name_forbidden(full_module_name)
|
| 505 |
+
|
| 506 |
+
if options.relative_path_in_code_position_comments:
|
| 507 |
+
rel_path = full_module_name.replace('.', os.sep) + source_ext
|
| 508 |
+
if not abs_path.endswith(rel_path):
|
| 509 |
+
rel_path = source # safety measure to prevent printing incorrect paths
|
| 510 |
+
else:
|
| 511 |
+
rel_path = abs_path
|
| 512 |
+
source_desc = FileSourceDescriptor(abs_path, rel_path)
|
| 513 |
+
source = CompilationSource(source_desc, full_module_name, cwd)
|
| 514 |
+
|
| 515 |
+
# Set up result object
|
| 516 |
+
result = create_default_resultobj(source, options)
|
| 517 |
+
|
| 518 |
+
if options.annotate is None:
|
| 519 |
+
# By default, decide based on whether an html file already exists.
|
| 520 |
+
html_filename = os.path.splitext(result.c_file)[0] + ".html"
|
| 521 |
+
if os.path.exists(html_filename):
|
| 522 |
+
with io.open(html_filename, "r", encoding="UTF-8") as html_file:
|
| 523 |
+
if u'<!-- Generated by Cython' in html_file.read(100):
|
| 524 |
+
options.annotate = True
|
| 525 |
+
|
| 526 |
+
# Get pipeline
|
| 527 |
+
if source_ext.lower() == '.py' or not source_ext:
|
| 528 |
+
pipeline = Pipeline.create_py_pipeline(context, options, result)
|
| 529 |
+
else:
|
| 530 |
+
pipeline = Pipeline.create_pyx_pipeline(context, options, result)
|
| 531 |
+
|
| 532 |
+
context.setup_errors(options, result)
|
| 533 |
+
|
| 534 |
+
if '.' in full_module_name and '.' in os.path.splitext(os.path.basename(abs_path))[0]:
|
| 535 |
+
warning((source_desc, 1, 0),
|
| 536 |
+
"Dotted filenames ('%s') are deprecated."
|
| 537 |
+
" Please use the normal Python package directory layout." % os.path.basename(abs_path), level=1)
|
| 538 |
+
|
| 539 |
+
err, enddata = Pipeline.run_pipeline(pipeline, source)
|
| 540 |
+
context.teardown_errors(err, options, result)
|
| 541 |
+
if err is None and options.depfile:
|
| 542 |
+
from ..Build.Dependencies import create_dependency_tree
|
| 543 |
+
dependencies = create_dependency_tree(context).all_dependencies(result.main_source_file)
|
| 544 |
+
Utils.write_depfile(result.c_file, result.main_source_file, dependencies)
|
| 545 |
+
return result
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
# ------------------------------------------------------------------------
|
| 549 |
+
#
|
| 550 |
+
# Main Python entry points
|
| 551 |
+
#
|
| 552 |
+
# ------------------------------------------------------------------------
|
| 553 |
+
|
| 554 |
+
class CompilationSource(object):
|
| 555 |
+
"""
|
| 556 |
+
Contains the data necessary to start up a compilation pipeline for
|
| 557 |
+
a single compilation unit.
|
| 558 |
+
"""
|
| 559 |
+
def __init__(self, source_desc, full_module_name, cwd):
|
| 560 |
+
self.source_desc = source_desc
|
| 561 |
+
self.full_module_name = full_module_name
|
| 562 |
+
self.cwd = cwd
|
| 563 |
+
|
| 564 |
+
|
| 565 |
+
class CompilationResult(object):
|
| 566 |
+
"""
|
| 567 |
+
Results from the Cython compiler:
|
| 568 |
+
|
| 569 |
+
c_file string or None The generated C source file
|
| 570 |
+
h_file string or None The generated C header file
|
| 571 |
+
i_file string or None The generated .pxi file
|
| 572 |
+
api_file string or None The generated C API .h file
|
| 573 |
+
listing_file string or None File of error messages
|
| 574 |
+
object_file string or None Result of compiling the C file
|
| 575 |
+
extension_file string or None Result of linking the object file
|
| 576 |
+
num_errors integer Number of compilation errors
|
| 577 |
+
compilation_source CompilationSource
|
| 578 |
+
"""
|
| 579 |
+
|
| 580 |
+
def __init__(self):
|
| 581 |
+
self.c_file = None
|
| 582 |
+
self.h_file = None
|
| 583 |
+
self.i_file = None
|
| 584 |
+
self.api_file = None
|
| 585 |
+
self.listing_file = None
|
| 586 |
+
self.object_file = None
|
| 587 |
+
self.extension_file = None
|
| 588 |
+
self.main_source_file = None
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
class CompilationResultSet(dict):
|
| 592 |
+
"""
|
| 593 |
+
Results from compiling multiple Pyrex source files. A mapping
|
| 594 |
+
from source file paths to CompilationResult instances. Also
|
| 595 |
+
has the following attributes:
|
| 596 |
+
|
| 597 |
+
num_errors integer Total number of compilation errors
|
| 598 |
+
"""
|
| 599 |
+
|
| 600 |
+
num_errors = 0
|
| 601 |
+
|
| 602 |
+
def add(self, source, result):
|
| 603 |
+
self[source] = result
|
| 604 |
+
self.num_errors += result.num_errors
|
| 605 |
+
|
| 606 |
+
|
| 607 |
+
def compile_single(source, options, full_module_name = None):
|
| 608 |
+
"""
|
| 609 |
+
compile_single(source, options, full_module_name)
|
| 610 |
+
|
| 611 |
+
Compile the given Pyrex implementation file and return a CompilationResult.
|
| 612 |
+
Always compiles a single file; does not perform timestamp checking or
|
| 613 |
+
recursion.
|
| 614 |
+
"""
|
| 615 |
+
return run_pipeline(source, options, full_module_name)
|
| 616 |
+
|
| 617 |
+
|
| 618 |
+
def compile_multiple(sources, options):
|
| 619 |
+
"""
|
| 620 |
+
compile_multiple(sources, options)
|
| 621 |
+
|
| 622 |
+
Compiles the given sequence of Pyrex implementation files and returns
|
| 623 |
+
a CompilationResultSet. Performs timestamp checking and/or recursion
|
| 624 |
+
if these are specified in the options.
|
| 625 |
+
"""
|
| 626 |
+
if len(sources) > 1 and options.module_name:
|
| 627 |
+
raise RuntimeError('Full module name can only be set '
|
| 628 |
+
'for single source compilation')
|
| 629 |
+
# run_pipeline creates the context
|
| 630 |
+
# context = Context.from_options(options)
|
| 631 |
+
sources = [os.path.abspath(source) for source in sources]
|
| 632 |
+
processed = set()
|
| 633 |
+
results = CompilationResultSet()
|
| 634 |
+
timestamps = options.timestamps
|
| 635 |
+
verbose = options.verbose
|
| 636 |
+
context = None
|
| 637 |
+
cwd = os.getcwd()
|
| 638 |
+
for source in sources:
|
| 639 |
+
if source not in processed:
|
| 640 |
+
if context is None:
|
| 641 |
+
context = Context.from_options(options)
|
| 642 |
+
output_filename = get_output_filename(source, cwd, options)
|
| 643 |
+
out_of_date = context.c_file_out_of_date(source, output_filename)
|
| 644 |
+
if (not timestamps) or out_of_date:
|
| 645 |
+
if verbose:
|
| 646 |
+
sys.stderr.write("Compiling %s\n" % source)
|
| 647 |
+
result = run_pipeline(source, options,
|
| 648 |
+
full_module_name=options.module_name,
|
| 649 |
+
context=context)
|
| 650 |
+
results.add(source, result)
|
| 651 |
+
# Compiling multiple sources in one context doesn't quite
|
| 652 |
+
# work properly yet.
|
| 653 |
+
context = None
|
| 654 |
+
processed.add(source)
|
| 655 |
+
return results
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
def compile(source, options = None, full_module_name = None, **kwds):
|
| 659 |
+
"""
|
| 660 |
+
compile(source [, options], [, <option> = <value>]...)
|
| 661 |
+
|
| 662 |
+
Compile one or more Pyrex implementation files, with optional timestamp
|
| 663 |
+
checking and recursing on dependencies. The source argument may be a string
|
| 664 |
+
or a sequence of strings. If it is a string and no recursion or timestamp
|
| 665 |
+
checking is requested, a CompilationResult is returned, otherwise a
|
| 666 |
+
CompilationResultSet is returned.
|
| 667 |
+
"""
|
| 668 |
+
options = CompilationOptions(defaults = options, **kwds)
|
| 669 |
+
if isinstance(source, basestring):
|
| 670 |
+
if not options.timestamps:
|
| 671 |
+
return compile_single(source, options, full_module_name)
|
| 672 |
+
source = [source]
|
| 673 |
+
return compile_multiple(source, options)
|
| 674 |
+
|
| 675 |
+
|
| 676 |
+
@Utils.cached_function
|
| 677 |
+
def search_include_directories(dirs, qualified_name, suffix="", pos=None, include=False, source_file_path=None):
|
| 678 |
+
"""
|
| 679 |
+
Search the list of include directories for the given file name.
|
| 680 |
+
|
| 681 |
+
If a source file path or position is given, first searches the directory
|
| 682 |
+
containing that file. Returns None if not found, but does not report an error.
|
| 683 |
+
|
| 684 |
+
The 'include' option will disable package dereferencing.
|
| 685 |
+
"""
|
| 686 |
+
if pos and not source_file_path:
|
| 687 |
+
file_desc = pos[0]
|
| 688 |
+
if not isinstance(file_desc, FileSourceDescriptor):
|
| 689 |
+
raise RuntimeError("Only file sources for code supported")
|
| 690 |
+
source_file_path = file_desc.filename
|
| 691 |
+
if source_file_path:
|
| 692 |
+
if include:
|
| 693 |
+
dirs = (os.path.dirname(source_file_path),) + dirs
|
| 694 |
+
else:
|
| 695 |
+
dirs = (Utils.find_root_package_dir(source_file_path),) + dirs
|
| 696 |
+
|
| 697 |
+
# search for dotted filename e.g. <dir>/foo.bar.pxd
|
| 698 |
+
dotted_filename = qualified_name
|
| 699 |
+
if suffix:
|
| 700 |
+
dotted_filename += suffix
|
| 701 |
+
|
| 702 |
+
for dirname in dirs:
|
| 703 |
+
path = os.path.join(dirname, dotted_filename)
|
| 704 |
+
if os.path.exists(path):
|
| 705 |
+
return path
|
| 706 |
+
|
| 707 |
+
# search for filename in package structure e.g. <dir>/foo/bar.pxd or <dir>/foo/bar/__init__.pxd
|
| 708 |
+
if not include:
|
| 709 |
+
|
| 710 |
+
names = qualified_name.split('.')
|
| 711 |
+
package_names = tuple(names[:-1])
|
| 712 |
+
module_name = names[-1]
|
| 713 |
+
|
| 714 |
+
# search for standard packages first - PEP420
|
| 715 |
+
namespace_dirs = []
|
| 716 |
+
for dirname in dirs:
|
| 717 |
+
package_dir, is_namespace = Utils.check_package_dir(dirname, package_names)
|
| 718 |
+
if package_dir is not None:
|
| 719 |
+
if is_namespace:
|
| 720 |
+
namespace_dirs.append(package_dir)
|
| 721 |
+
continue
|
| 722 |
+
path = search_module_in_dir(package_dir, module_name, suffix)
|
| 723 |
+
if path:
|
| 724 |
+
return path
|
| 725 |
+
|
| 726 |
+
# search for namespaces second - PEP420
|
| 727 |
+
for package_dir in namespace_dirs:
|
| 728 |
+
path = search_module_in_dir(package_dir, module_name, suffix)
|
| 729 |
+
if path:
|
| 730 |
+
return path
|
| 731 |
+
|
| 732 |
+
return None
|
| 733 |
+
|
| 734 |
+
|
| 735 |
+
@Utils.cached_function
|
| 736 |
+
def search_module_in_dir(package_dir, module_name, suffix):
|
| 737 |
+
# matches modules of the form: <dir>/foo/bar.pxd
|
| 738 |
+
path = Utils.find_versioned_file(package_dir, module_name, suffix)
|
| 739 |
+
|
| 740 |
+
# matches modules of the form: <dir>/foo/bar/__init__.pxd
|
| 741 |
+
if not path and suffix:
|
| 742 |
+
path = Utils.find_versioned_file(os.path.join(package_dir, module_name), "__init__", suffix)
|
| 743 |
+
|
| 744 |
+
return path
|
| 745 |
+
|
| 746 |
+
|
| 747 |
+
# ------------------------------------------------------------------------
|
| 748 |
+
#
|
| 749 |
+
# Main command-line entry point
|
| 750 |
+
#
|
| 751 |
+
# ------------------------------------------------------------------------
|
| 752 |
+
|
| 753 |
+
def setuptools_main():
|
| 754 |
+
return main(command_line = 1)
|
| 755 |
+
|
| 756 |
+
|
| 757 |
+
def main(command_line = 0):
|
| 758 |
+
args = sys.argv[1:]
|
| 759 |
+
any_failures = 0
|
| 760 |
+
if command_line:
|
| 761 |
+
try:
|
| 762 |
+
options, sources = parse_command_line(args)
|
| 763 |
+
except IOError as e:
|
| 764 |
+
# TODO: IOError can be replaced with FileNotFoundError in Cython 3.1
|
| 765 |
+
import errno
|
| 766 |
+
if errno.ENOENT != e.errno:
|
| 767 |
+
# Raised IOError is not caused by missing file.
|
| 768 |
+
raise
|
| 769 |
+
print("{}: No such file or directory: '{}'".format(sys.argv[0], e.filename), file=sys.stderr)
|
| 770 |
+
sys.exit(1)
|
| 771 |
+
else:
|
| 772 |
+
options = CompilationOptions(default_options)
|
| 773 |
+
sources = args
|
| 774 |
+
|
| 775 |
+
if options.show_version:
|
| 776 |
+
Utils.print_version()
|
| 777 |
+
|
| 778 |
+
if options.working_path!="":
|
| 779 |
+
os.chdir(options.working_path)
|
| 780 |
+
|
| 781 |
+
try:
|
| 782 |
+
result = compile(sources, options)
|
| 783 |
+
if result.num_errors > 0:
|
| 784 |
+
any_failures = 1
|
| 785 |
+
except (EnvironmentError, PyrexError) as e:
|
| 786 |
+
sys.stderr.write(str(e) + '\n')
|
| 787 |
+
any_failures = 1
|
| 788 |
+
if any_failures:
|
| 789 |
+
sys.exit(1)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Naming.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# C naming conventions
|
| 3 |
+
#
|
| 4 |
+
#
|
| 5 |
+
# Prefixes for generating C names.
|
| 6 |
+
# Collected here to facilitate ensuring uniqueness.
|
| 7 |
+
#
|
| 8 |
+
from .. import __version__
|
| 9 |
+
|
| 10 |
+
pyrex_prefix = "__pyx_"
|
| 11 |
+
cyversion = __version__.replace('.', '_')
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
codewriter_temp_prefix = pyrex_prefix + "t_"
|
| 15 |
+
|
| 16 |
+
temp_prefix = u"__cyt_"
|
| 17 |
+
|
| 18 |
+
pyunicode_identifier_prefix = pyrex_prefix + 'U'
|
| 19 |
+
|
| 20 |
+
builtin_prefix = pyrex_prefix + "builtin_"
|
| 21 |
+
arg_prefix = pyrex_prefix + "arg_"
|
| 22 |
+
genexpr_arg_prefix = pyrex_prefix + "genexpr_arg_"
|
| 23 |
+
funcdoc_prefix = pyrex_prefix + "doc_"
|
| 24 |
+
enum_prefix = pyrex_prefix + "e_"
|
| 25 |
+
func_prefix = pyrex_prefix + "f_"
|
| 26 |
+
func_prefix_api = pyrex_prefix + "api_f_"
|
| 27 |
+
pyfunc_prefix = pyrex_prefix + "pf_"
|
| 28 |
+
pywrap_prefix = pyrex_prefix + "pw_"
|
| 29 |
+
genbody_prefix = pyrex_prefix + "gb_"
|
| 30 |
+
gstab_prefix = pyrex_prefix + "getsets_"
|
| 31 |
+
prop_get_prefix = pyrex_prefix + "getprop_"
|
| 32 |
+
const_prefix = pyrex_prefix + "k_"
|
| 33 |
+
py_const_prefix = pyrex_prefix + "kp_"
|
| 34 |
+
label_prefix = pyrex_prefix + "L"
|
| 35 |
+
pymethdef_prefix = pyrex_prefix + "mdef_"
|
| 36 |
+
method_wrapper_prefix = pyrex_prefix + "specialmethod_"
|
| 37 |
+
methtab_prefix = pyrex_prefix + "methods_"
|
| 38 |
+
memtab_prefix = pyrex_prefix + "members_"
|
| 39 |
+
objstruct_prefix = pyrex_prefix + "obj_"
|
| 40 |
+
typeptr_prefix = pyrex_prefix + "ptype_"
|
| 41 |
+
prop_set_prefix = pyrex_prefix + "setprop_"
|
| 42 |
+
type_prefix = pyrex_prefix + "t_"
|
| 43 |
+
typeobj_prefix = pyrex_prefix + "type_"
|
| 44 |
+
var_prefix = pyrex_prefix + "v_"
|
| 45 |
+
varptr_prefix = pyrex_prefix + "vp_"
|
| 46 |
+
varptr_prefix_api = pyrex_prefix + "api_vp_"
|
| 47 |
+
wrapperbase_prefix= pyrex_prefix + "wrapperbase_"
|
| 48 |
+
pybuffernd_prefix = pyrex_prefix + "pybuffernd_"
|
| 49 |
+
pybufferstruct_prefix = pyrex_prefix + "pybuffer_"
|
| 50 |
+
vtable_prefix = pyrex_prefix + "vtable_"
|
| 51 |
+
vtabptr_prefix = pyrex_prefix + "vtabptr_"
|
| 52 |
+
vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
|
| 53 |
+
unicode_vtabentry_prefix = pyrex_prefix + "Uvtabentry_"
|
| 54 |
+
# vtab entries aren't normally mangled,
|
| 55 |
+
# but punycode names sometimes start with numbers leading to a C syntax error
|
| 56 |
+
unicode_structmember_prefix = pyrex_prefix + "Umember_"
|
| 57 |
+
# as above -
|
| 58 |
+
# not normally mangled but punycode names cause specific problems
|
| 59 |
+
opt_arg_prefix = pyrex_prefix + "opt_args_"
|
| 60 |
+
convert_func_prefix = pyrex_prefix + "convert_"
|
| 61 |
+
closure_scope_prefix = pyrex_prefix + "scope_"
|
| 62 |
+
closure_class_prefix = pyrex_prefix + "scope_struct_"
|
| 63 |
+
lambda_func_prefix = pyrex_prefix + "lambda_"
|
| 64 |
+
module_is_main = pyrex_prefix + "module_is_main"
|
| 65 |
+
defaults_struct_prefix = pyrex_prefix + "defaults"
|
| 66 |
+
dynamic_args_cname = pyrex_prefix + "dynamic_args"
|
| 67 |
+
|
| 68 |
+
interned_prefixes = {
|
| 69 |
+
'str': pyrex_prefix + "n_",
|
| 70 |
+
'int': pyrex_prefix + "int_",
|
| 71 |
+
'float': pyrex_prefix + "float_",
|
| 72 |
+
'tuple': pyrex_prefix + "tuple_",
|
| 73 |
+
'codeobj': pyrex_prefix + "codeobj_",
|
| 74 |
+
'slice': pyrex_prefix + "slice_",
|
| 75 |
+
'ustring': pyrex_prefix + "ustring_",
|
| 76 |
+
'umethod': pyrex_prefix + "umethod_",
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
ctuple_type_prefix = pyrex_prefix + "ctuple_"
|
| 80 |
+
args_cname = pyrex_prefix + "args"
|
| 81 |
+
nargs_cname = pyrex_prefix + "nargs"
|
| 82 |
+
kwvalues_cname = pyrex_prefix + "kwvalues"
|
| 83 |
+
generator_cname = pyrex_prefix + "generator"
|
| 84 |
+
sent_value_cname = pyrex_prefix + "sent_value"
|
| 85 |
+
pykwdlist_cname = pyrex_prefix + "pyargnames"
|
| 86 |
+
obj_base_cname = pyrex_prefix + "base"
|
| 87 |
+
builtins_cname = pyrex_prefix + "b"
|
| 88 |
+
preimport_cname = pyrex_prefix + "i"
|
| 89 |
+
moddict_cname = pyrex_prefix + "d"
|
| 90 |
+
dummy_cname = pyrex_prefix + "dummy"
|
| 91 |
+
filename_cname = pyrex_prefix + "filename"
|
| 92 |
+
modulename_cname = pyrex_prefix + "modulename"
|
| 93 |
+
filetable_cname = pyrex_prefix + "f"
|
| 94 |
+
intern_tab_cname = pyrex_prefix + "intern_tab"
|
| 95 |
+
kwds_cname = pyrex_prefix + "kwds"
|
| 96 |
+
lineno_cname = pyrex_prefix + "lineno"
|
| 97 |
+
clineno_cname = pyrex_prefix + "clineno"
|
| 98 |
+
cfilenm_cname = pyrex_prefix + "cfilenm"
|
| 99 |
+
local_tstate_cname = pyrex_prefix + "tstate"
|
| 100 |
+
module_cname = pyrex_prefix + "m"
|
| 101 |
+
modulestate_cname = pyrex_prefix + "mstate"
|
| 102 |
+
modulestateglobal_cname = pyrex_prefix + "mstate_global"
|
| 103 |
+
moddoc_cname = pyrex_prefix + "mdoc"
|
| 104 |
+
methtable_cname = pyrex_prefix + "methods"
|
| 105 |
+
retval_cname = pyrex_prefix + "r"
|
| 106 |
+
reqd_kwds_cname = pyrex_prefix + "reqd_kwds"
|
| 107 |
+
self_cname = pyrex_prefix + "self"
|
| 108 |
+
stringtab_cname = pyrex_prefix + "string_tab"
|
| 109 |
+
vtabslot_cname = pyrex_prefix + "vtab"
|
| 110 |
+
c_api_tab_cname = pyrex_prefix + "c_api_tab"
|
| 111 |
+
gilstate_cname = pyrex_prefix + "state"
|
| 112 |
+
skip_dispatch_cname = pyrex_prefix + "skip_dispatch"
|
| 113 |
+
empty_tuple = pyrex_prefix + "empty_tuple"
|
| 114 |
+
empty_bytes = pyrex_prefix + "empty_bytes"
|
| 115 |
+
empty_unicode = pyrex_prefix + "empty_unicode"
|
| 116 |
+
print_function = pyrex_prefix + "print"
|
| 117 |
+
print_function_kwargs = pyrex_prefix + "print_kwargs"
|
| 118 |
+
cleanup_cname = pyrex_prefix + "module_cleanup"
|
| 119 |
+
pymoduledef_cname = pyrex_prefix + "moduledef"
|
| 120 |
+
pymoduledef_slots_cname = pyrex_prefix + "moduledef_slots"
|
| 121 |
+
pymodinit_module_arg = pyrex_prefix + "pyinit_module"
|
| 122 |
+
pymodule_create_func_cname = pyrex_prefix + "pymod_create"
|
| 123 |
+
pymodule_exec_func_cname = pyrex_prefix + "pymod_exec"
|
| 124 |
+
optional_args_cname = pyrex_prefix + "optional_args"
|
| 125 |
+
import_star = pyrex_prefix + "import_star"
|
| 126 |
+
import_star_set = pyrex_prefix + "import_star_set"
|
| 127 |
+
outer_scope_cname= pyrex_prefix + "outer_scope"
|
| 128 |
+
cur_scope_cname = pyrex_prefix + "cur_scope"
|
| 129 |
+
enc_scope_cname = pyrex_prefix + "enc_scope"
|
| 130 |
+
frame_cname = pyrex_prefix + "frame"
|
| 131 |
+
frame_code_cname = pyrex_prefix + "frame_code"
|
| 132 |
+
error_without_exception_cname = pyrex_prefix + "error_without_exception"
|
| 133 |
+
binding_cfunc = pyrex_prefix + "binding_PyCFunctionType"
|
| 134 |
+
fused_func_prefix = pyrex_prefix + 'fuse_'
|
| 135 |
+
fused_dtype_prefix = pyrex_prefix + 'fused_dtype_'
|
| 136 |
+
quick_temp_cname = pyrex_prefix + "temp" # temp variable for quick'n'dirty temping
|
| 137 |
+
tp_dict_version_temp = pyrex_prefix + "tp_dict_version"
|
| 138 |
+
obj_dict_version_temp = pyrex_prefix + "obj_dict_version"
|
| 139 |
+
type_dict_guard_temp = pyrex_prefix + "typedict_guard"
|
| 140 |
+
cython_runtime_cname = pyrex_prefix + "cython_runtime"
|
| 141 |
+
cyfunction_type_cname = pyrex_prefix + "CyFunctionType"
|
| 142 |
+
fusedfunction_type_cname = pyrex_prefix + "FusedFunctionType"
|
| 143 |
+
# the name "dflt" was picked by analogy with the CPython dataclass module which stores
|
| 144 |
+
# the default values in variables named f"_dflt_{field.name}" in a hidden scope that's
|
| 145 |
+
# passed to the __init__ function. (The name is unimportant to the exact workings though)
|
| 146 |
+
dataclass_field_default_cname = pyrex_prefix + "dataclass_dflt"
|
| 147 |
+
|
| 148 |
+
global_code_object_cache_find = pyrex_prefix + 'find_code_object'
|
| 149 |
+
global_code_object_cache_insert = pyrex_prefix + 'insert_code_object'
|
| 150 |
+
|
| 151 |
+
genexpr_id_ref = 'genexpr'
|
| 152 |
+
freelist_name = 'freelist'
|
| 153 |
+
freecount_name = 'freecount'
|
| 154 |
+
|
| 155 |
+
line_c_macro = "__LINE__"
|
| 156 |
+
|
| 157 |
+
file_c_macro = "__FILE__"
|
| 158 |
+
|
| 159 |
+
extern_c_macro = pyrex_prefix.upper() + "EXTERN_C"
|
| 160 |
+
|
| 161 |
+
exc_type_name = pyrex_prefix + "exc_type"
|
| 162 |
+
exc_value_name = pyrex_prefix + "exc_value"
|
| 163 |
+
exc_tb_name = pyrex_prefix + "exc_tb"
|
| 164 |
+
exc_lineno_name = pyrex_prefix + "exc_lineno"
|
| 165 |
+
|
| 166 |
+
parallel_exc_type = pyrex_prefix + "parallel_exc_type"
|
| 167 |
+
parallel_exc_value = pyrex_prefix + "parallel_exc_value"
|
| 168 |
+
parallel_exc_tb = pyrex_prefix + "parallel_exc_tb"
|
| 169 |
+
parallel_filename = pyrex_prefix + "parallel_filename"
|
| 170 |
+
parallel_lineno = pyrex_prefix + "parallel_lineno"
|
| 171 |
+
parallel_clineno = pyrex_prefix + "parallel_clineno"
|
| 172 |
+
parallel_why = pyrex_prefix + "parallel_why"
|
| 173 |
+
|
| 174 |
+
exc_vars = (exc_type_name, exc_value_name, exc_tb_name)
|
| 175 |
+
|
| 176 |
+
api_name = pyrex_prefix + "capi__"
|
| 177 |
+
|
| 178 |
+
# the h and api guards get changed to:
|
| 179 |
+
# __PYX_HAVE__FILENAME (for ascii filenames)
|
| 180 |
+
# __PYX_HAVE_U_PUNYCODEFILENAME (for non-ascii filenames)
|
| 181 |
+
h_guard_prefix = "__PYX_HAVE_"
|
| 182 |
+
api_guard_prefix = "__PYX_HAVE_API_"
|
| 183 |
+
api_func_guard = "__PYX_HAVE_API_FUNC_"
|
| 184 |
+
|
| 185 |
+
PYX_NAN = "__PYX_NAN()"
|
| 186 |
+
|
| 187 |
+
def py_version_hex(major, minor=0, micro=0, release_level=0, release_serial=0):
|
| 188 |
+
return (major << 24) | (minor << 16) | (micro << 8) | (release_level << 4) | (release_serial)
|
| 189 |
+
|
| 190 |
+
# there's a few places where it's useful to iterate over all of these
|
| 191 |
+
used_types_and_macros = [
|
| 192 |
+
(cyfunction_type_cname, '__Pyx_CyFunction_USED'),
|
| 193 |
+
(fusedfunction_type_cname, '__Pyx_FusedFunction_USED'),
|
| 194 |
+
('__pyx_GeneratorType', '__Pyx_Generator_USED'),
|
| 195 |
+
('__pyx_IterableCoroutineType', '__Pyx_IterableCoroutine_USED'),
|
| 196 |
+
('__pyx_CoroutineAwaitType', '__Pyx_Coroutine_USED'),
|
| 197 |
+
('__pyx_CoroutineType', '__Pyx_Coroutine_USED'),
|
| 198 |
+
]
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Optimize.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/ParseTreeTransforms.pxd
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: language_level=3str
|
| 2 |
+
|
| 3 |
+
cimport cython
|
| 4 |
+
|
| 5 |
+
from .Visitor cimport (
|
| 6 |
+
CythonTransform, VisitorTransform, TreeVisitor,
|
| 7 |
+
ScopeTrackingTransform, EnvTransform)
|
| 8 |
+
|
| 9 |
+
# Don't include mixins, only the main classes.
|
| 10 |
+
#cdef class SkipDeclarations:
|
| 11 |
+
|
| 12 |
+
cdef class NormalizeTree(CythonTransform):
|
| 13 |
+
cdef bint is_in_statlist
|
| 14 |
+
cdef bint is_in_expr
|
| 15 |
+
cpdef visit_StatNode(self, node, is_listcontainer=*)
|
| 16 |
+
|
| 17 |
+
cdef class PostParse(ScopeTrackingTransform):
|
| 18 |
+
cdef dict specialattribute_handlers
|
| 19 |
+
cdef size_t lambda_counter
|
| 20 |
+
cdef size_t genexpr_counter
|
| 21 |
+
cdef _visit_assignment_node(self, node, list expr_list)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
#def eliminate_rhs_duplicates(list expr_list_list, list ref_node_sequence)
|
| 25 |
+
#def sort_common_subsequences(list items)
|
| 26 |
+
@cython.locals(starred_targets=Py_ssize_t, lhs_size=Py_ssize_t, rhs_size=Py_ssize_t)
|
| 27 |
+
cdef flatten_parallel_assignments(list input, list output)
|
| 28 |
+
cdef map_starred_assignment(list lhs_targets, list starred_assignments, list lhs_args, list rhs_args)
|
| 29 |
+
|
| 30 |
+
#class PxdPostParse(CythonTransform, SkipDeclarations):
|
| 31 |
+
#class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
|
| 32 |
+
#class WithTransform(VisitorTransform, SkipDeclarations):
|
| 33 |
+
#class DecoratorTransform(CythonTransform, SkipDeclarations):
|
| 34 |
+
|
| 35 |
+
#class AnalyseDeclarationsTransform(EnvTransform):
|
| 36 |
+
|
| 37 |
+
cdef class AnalyseExpressionsTransform(CythonTransform):
|
| 38 |
+
pass
|
| 39 |
+
|
| 40 |
+
cdef class ExpandInplaceOperators(EnvTransform):
|
| 41 |
+
pass
|
| 42 |
+
|
| 43 |
+
cdef class AlignFunctionDefinitions(CythonTransform):
|
| 44 |
+
cdef dict directives
|
| 45 |
+
cdef set imported_names
|
| 46 |
+
cdef object scope
|
| 47 |
+
|
| 48 |
+
@cython.final
|
| 49 |
+
cdef class YieldNodeCollector(TreeVisitor):
|
| 50 |
+
cdef public list yields
|
| 51 |
+
cdef public list returns
|
| 52 |
+
cdef public list finallys
|
| 53 |
+
cdef public list excepts
|
| 54 |
+
cdef public bint has_return_value
|
| 55 |
+
cdef public bint has_yield
|
| 56 |
+
cdef public bint has_await
|
| 57 |
+
cdef list excludes
|
| 58 |
+
|
| 59 |
+
@cython.final
|
| 60 |
+
cdef class MarkClosureVisitor(CythonTransform):
|
| 61 |
+
cdef bint needs_closure
|
| 62 |
+
cdef list excludes
|
| 63 |
+
|
| 64 |
+
@cython.final
|
| 65 |
+
cdef class CreateClosureClasses(CythonTransform):
|
| 66 |
+
cdef list path
|
| 67 |
+
cdef bint in_lambda
|
| 68 |
+
cdef module_scope
|
| 69 |
+
cdef generator_class
|
| 70 |
+
|
| 71 |
+
cdef create_class_from_scope(self, node, target_module_scope, inner_node=*)
|
| 72 |
+
cdef find_entries_used_in_closures(self, node)
|
| 73 |
+
|
| 74 |
+
#cdef class InjectGilHandling(VisitorTransform, SkipDeclarations):
|
| 75 |
+
# cdef bint nogil
|
| 76 |
+
|
| 77 |
+
cdef class GilCheck(VisitorTransform):
|
| 78 |
+
cdef list env_stack
|
| 79 |
+
cdef bint nogil
|
| 80 |
+
cdef bint nogil_declarator_only
|
| 81 |
+
cdef bint current_gilstat_node_knows_gil_state
|
| 82 |
+
|
| 83 |
+
cdef class TransformBuiltinMethods(EnvTransform):
|
| 84 |
+
cdef visit_cython_attribute(self, node)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Parsing.cpython-311-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:710a5e569000a869790e4771a77758935facb69c3b699ae88bbe65b9f2bf98a2
|
| 3 |
+
size 1170440
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Parsing.pxd
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: language_level=3
|
| 2 |
+
|
| 3 |
+
# We declare all of these here to type the first argument.
|
| 4 |
+
|
| 5 |
+
from __future__ import absolute_import
|
| 6 |
+
|
| 7 |
+
cimport cython
|
| 8 |
+
from .Scanning cimport PyrexScanner
|
| 9 |
+
|
| 10 |
+
ctypedef object (*p_sub_expr_func)(PyrexScanner obj)
|
| 11 |
+
|
| 12 |
+
# entry points
|
| 13 |
+
|
| 14 |
+
cpdef p_module(PyrexScanner s, pxd, full_module_name, ctx=*)
|
| 15 |
+
cpdef p_code(PyrexScanner s, level= *, ctx=*)
|
| 16 |
+
|
| 17 |
+
# internal parser states
|
| 18 |
+
|
| 19 |
+
cdef p_ident(PyrexScanner s, message =*)
|
| 20 |
+
cdef p_ident_list(PyrexScanner s)
|
| 21 |
+
|
| 22 |
+
cdef tuple p_binop_operator(PyrexScanner s)
|
| 23 |
+
cdef p_binop_expr(PyrexScanner s, ops, p_sub_expr_func p_sub_expr)
|
| 24 |
+
cdef p_lambdef(PyrexScanner s)
|
| 25 |
+
cdef p_test(PyrexScanner s)
|
| 26 |
+
cdef p_test_allow_walrus_after(PyrexScanner s)
|
| 27 |
+
cdef p_namedexpr_test(PyrexScanner s)
|
| 28 |
+
cdef p_or_test(PyrexScanner s)
|
| 29 |
+
cdef p_rassoc_binop_expr(PyrexScanner s, unicode op, p_sub_expr_func p_subexpr)
|
| 30 |
+
cdef p_and_test(PyrexScanner s)
|
| 31 |
+
cdef p_not_test(PyrexScanner s)
|
| 32 |
+
cdef p_comparison(PyrexScanner s)
|
| 33 |
+
cdef p_test_or_starred_expr(PyrexScanner s)
|
| 34 |
+
cdef p_namedexpr_test_or_starred_expr(PyrexScanner s)
|
| 35 |
+
cdef p_starred_expr(PyrexScanner s)
|
| 36 |
+
cdef p_cascaded_cmp(PyrexScanner s)
|
| 37 |
+
cdef p_cmp_op(PyrexScanner s)
|
| 38 |
+
cdef p_bit_expr(PyrexScanner s)
|
| 39 |
+
cdef p_xor_expr(PyrexScanner s)
|
| 40 |
+
cdef p_and_expr(PyrexScanner s)
|
| 41 |
+
cdef p_shift_expr(PyrexScanner s)
|
| 42 |
+
cdef p_arith_expr(PyrexScanner s)
|
| 43 |
+
cdef p_term(PyrexScanner s)
|
| 44 |
+
cdef p_factor(PyrexScanner s)
|
| 45 |
+
cdef _p_factor(PyrexScanner s)
|
| 46 |
+
cdef p_typecast(PyrexScanner s)
|
| 47 |
+
cdef p_sizeof(PyrexScanner s)
|
| 48 |
+
cdef p_yield_expression(PyrexScanner s)
|
| 49 |
+
cdef p_yield_statement(PyrexScanner s)
|
| 50 |
+
cdef p_async_statement(PyrexScanner s, ctx, decorators)
|
| 51 |
+
cdef p_power(PyrexScanner s)
|
| 52 |
+
cdef p_new_expr(PyrexScanner s)
|
| 53 |
+
cdef p_trailer(PyrexScanner s, node1)
|
| 54 |
+
cdef p_call_parse_args(PyrexScanner s, bint allow_genexp = *)
|
| 55 |
+
cdef p_call_build_packed_args(pos, positional_args, keyword_args)
|
| 56 |
+
cdef p_call(PyrexScanner s, function)
|
| 57 |
+
cdef p_index(PyrexScanner s, base)
|
| 58 |
+
cdef tuple p_subscript_list(PyrexScanner s)
|
| 59 |
+
cdef p_subscript(PyrexScanner s)
|
| 60 |
+
cdef p_slice_element(PyrexScanner s, follow_set)
|
| 61 |
+
cdef expect_ellipsis(PyrexScanner s)
|
| 62 |
+
cdef make_slice_nodes(pos, subscripts)
|
| 63 |
+
cpdef make_slice_node(pos, start, stop = *, step = *)
|
| 64 |
+
cdef p_atom(PyrexScanner s)
|
| 65 |
+
@cython.locals(value=unicode)
|
| 66 |
+
cdef p_int_literal(PyrexScanner s)
|
| 67 |
+
cdef p_name(PyrexScanner s, name)
|
| 68 |
+
cdef wrap_compile_time_constant(pos, value)
|
| 69 |
+
cdef p_cat_string_literal(PyrexScanner s)
|
| 70 |
+
cdef p_opt_string_literal(PyrexScanner s, required_type=*)
|
| 71 |
+
cdef bint check_for_non_ascii_characters(unicode string)
|
| 72 |
+
@cython.locals(systr=unicode, is_python3_source=bint, is_raw=bint)
|
| 73 |
+
cdef p_string_literal(PyrexScanner s, kind_override=*)
|
| 74 |
+
cdef _append_escape_sequence(kind, builder, unicode escape_sequence, PyrexScanner s)
|
| 75 |
+
cdef tuple _f_string_error_pos(pos, string, Py_ssize_t i)
|
| 76 |
+
@cython.locals(i=Py_ssize_t, size=Py_ssize_t, c=Py_UCS4, next_start=Py_ssize_t)
|
| 77 |
+
cdef list p_f_string(PyrexScanner s, unicode_value, pos, bint is_raw)
|
| 78 |
+
@cython.locals(i=Py_ssize_t, size=Py_ssize_t, c=Py_UCS4, quote_char=Py_UCS4, NO_CHAR=Py_UCS4)
|
| 79 |
+
cdef tuple p_f_string_expr(PyrexScanner s, unicode_value, pos, Py_ssize_t starting_index, bint is_raw)
|
| 80 |
+
cdef p_list_maker(PyrexScanner s)
|
| 81 |
+
cdef p_comp_iter(PyrexScanner s, body)
|
| 82 |
+
cdef p_comp_for(PyrexScanner s, body)
|
| 83 |
+
cdef p_comp_if(PyrexScanner s, body)
|
| 84 |
+
cdef p_dict_or_set_maker(PyrexScanner s)
|
| 85 |
+
cdef p_backquote_expr(PyrexScanner s)
|
| 86 |
+
cdef p_simple_expr_list(PyrexScanner s, expr=*)
|
| 87 |
+
cdef p_test_or_starred_expr_list(PyrexScanner s, expr=*)
|
| 88 |
+
cdef p_namedexpr_test_or_starred_expr_list(s, expr=*)
|
| 89 |
+
cdef p_testlist(PyrexScanner s)
|
| 90 |
+
cdef p_testlist_star_expr(PyrexScanner s)
|
| 91 |
+
cdef p_testlist_comp(PyrexScanner s)
|
| 92 |
+
cdef p_genexp(PyrexScanner s, expr)
|
| 93 |
+
|
| 94 |
+
#-------------------------------------------------------
|
| 95 |
+
#
|
| 96 |
+
# Statements
|
| 97 |
+
#
|
| 98 |
+
#-------------------------------------------------------
|
| 99 |
+
|
| 100 |
+
cdef p_global_statement(PyrexScanner s)
|
| 101 |
+
cdef p_nonlocal_statement(PyrexScanner s)
|
| 102 |
+
cdef p_expression_or_assignment(PyrexScanner s)
|
| 103 |
+
cdef p_print_statement(PyrexScanner s)
|
| 104 |
+
cdef p_exec_statement(PyrexScanner s)
|
| 105 |
+
cdef p_del_statement(PyrexScanner s)
|
| 106 |
+
cdef p_pass_statement(PyrexScanner s, bint with_newline = *)
|
| 107 |
+
cdef p_break_statement(PyrexScanner s)
|
| 108 |
+
cdef p_continue_statement(PyrexScanner s)
|
| 109 |
+
cdef p_return_statement(PyrexScanner s)
|
| 110 |
+
cdef p_raise_statement(PyrexScanner s)
|
| 111 |
+
cdef p_import_statement(PyrexScanner s)
|
| 112 |
+
cdef p_from_import_statement(PyrexScanner s, bint first_statement = *)
|
| 113 |
+
cdef p_imported_name(PyrexScanner s)
|
| 114 |
+
cdef p_dotted_name(PyrexScanner s, bint as_allowed)
|
| 115 |
+
cdef p_as_name(PyrexScanner s)
|
| 116 |
+
cdef p_assert_statement(PyrexScanner s)
|
| 117 |
+
cdef p_if_statement(PyrexScanner s)
|
| 118 |
+
cdef p_if_clause(PyrexScanner s)
|
| 119 |
+
cdef p_else_clause(PyrexScanner s)
|
| 120 |
+
cdef p_while_statement(PyrexScanner s)
|
| 121 |
+
cdef p_for_statement(PyrexScanner s, bint is_async=*)
|
| 122 |
+
cdef dict p_for_bounds(PyrexScanner s, bint allow_testlist=*, bint is_async=*)
|
| 123 |
+
cdef p_for_from_relation(PyrexScanner s)
|
| 124 |
+
cdef p_for_from_step(PyrexScanner s)
|
| 125 |
+
cdef p_target(PyrexScanner s, terminator)
|
| 126 |
+
cdef p_for_target(PyrexScanner s)
|
| 127 |
+
cdef p_for_iterator(PyrexScanner s, bint allow_testlist=*, bint is_async=*)
|
| 128 |
+
cdef p_try_statement(PyrexScanner s)
|
| 129 |
+
cdef p_except_clause(PyrexScanner s)
|
| 130 |
+
cdef p_include_statement(PyrexScanner s, ctx)
|
| 131 |
+
cdef p_with_statement(PyrexScanner s)
|
| 132 |
+
cdef p_with_items(PyrexScanner s, bint is_async=*)
|
| 133 |
+
cdef p_with_items_list(PyrexScanner s, bint is_async)
|
| 134 |
+
cdef tuple p_with_item(PyrexScanner s, bint is_async)
|
| 135 |
+
cdef p_with_template(PyrexScanner s)
|
| 136 |
+
cdef p_simple_statement(PyrexScanner s, bint first_statement = *)
|
| 137 |
+
cdef p_simple_statement_list(PyrexScanner s, ctx, bint first_statement = *)
|
| 138 |
+
cdef p_compile_time_expr(PyrexScanner s)
|
| 139 |
+
cdef p_DEF_statement(PyrexScanner s)
|
| 140 |
+
cdef p_IF_statement(PyrexScanner s, ctx)
|
| 141 |
+
cdef p_statement(PyrexScanner s, ctx, bint first_statement = *)
|
| 142 |
+
cdef p_statement_list(PyrexScanner s, ctx, bint first_statement = *)
|
| 143 |
+
cdef p_suite(PyrexScanner s, ctx = *)
|
| 144 |
+
cdef tuple p_suite_with_docstring(PyrexScanner s, ctx, bint with_doc_only=*)
|
| 145 |
+
cdef tuple _extract_docstring(node)
|
| 146 |
+
cdef p_positional_and_keyword_args(PyrexScanner s, end_sy_set, templates = *)
|
| 147 |
+
|
| 148 |
+
cpdef p_c_base_type(PyrexScanner s, bint nonempty = *, templates = *)
|
| 149 |
+
cdef p_calling_convention(PyrexScanner s)
|
| 150 |
+
cdef p_c_complex_base_type(PyrexScanner s, templates = *)
|
| 151 |
+
cdef p_c_simple_base_type(PyrexScanner s, bint nonempty, templates = *)
|
| 152 |
+
cdef p_buffer_or_template(PyrexScanner s, base_type_node, templates)
|
| 153 |
+
cdef p_bracketed_base_type(PyrexScanner s, base_type_node, nonempty, empty)
|
| 154 |
+
cdef is_memoryviewslice_access(PyrexScanner s)
|
| 155 |
+
cdef p_memoryviewslice_access(PyrexScanner s, base_type_node)
|
| 156 |
+
cdef bint looking_at_name(PyrexScanner s) except -2
|
| 157 |
+
cdef object looking_at_expr(PyrexScanner s)# except -2
|
| 158 |
+
cdef bint looking_at_base_type(PyrexScanner s) except -2
|
| 159 |
+
cdef bint looking_at_dotted_name(PyrexScanner s) except -2
|
| 160 |
+
cdef p_sign_and_longness(PyrexScanner s)
|
| 161 |
+
cdef p_opt_cname(PyrexScanner s)
|
| 162 |
+
cpdef p_c_declarator(PyrexScanner s, ctx = *, bint empty = *, bint is_type = *, bint cmethod_flag = *,
|
| 163 |
+
bint assignable = *, bint nonempty = *,
|
| 164 |
+
bint calling_convention_allowed = *)
|
| 165 |
+
cdef p_c_array_declarator(PyrexScanner s, base)
|
| 166 |
+
cdef p_c_func_declarator(PyrexScanner s, pos, ctx, base, bint cmethod_flag)
|
| 167 |
+
cdef p_c_simple_declarator(PyrexScanner s, ctx, bint empty, bint is_type, bint cmethod_flag,
|
| 168 |
+
bint assignable, bint nonempty)
|
| 169 |
+
cdef p_nogil(PyrexScanner s)
|
| 170 |
+
cdef p_with_gil(PyrexScanner s)
|
| 171 |
+
cdef p_exception_value_clause(PyrexScanner s, bint is_extern)
|
| 172 |
+
cpdef p_c_arg_list(PyrexScanner s, ctx = *, bint in_pyfunc = *, bint cmethod_flag = *,
|
| 173 |
+
bint nonempty_declarators = *, bint kw_only = *, bint annotated = *)
|
| 174 |
+
cdef p_optional_ellipsis(PyrexScanner s)
|
| 175 |
+
cdef p_c_arg_decl(PyrexScanner s, ctx, in_pyfunc, bint cmethod_flag = *, bint nonempty = *, bint kw_only = *, bint annotated = *)
|
| 176 |
+
cdef p_api(PyrexScanner s)
|
| 177 |
+
cdef p_cdef_statement(PyrexScanner s, ctx)
|
| 178 |
+
cdef p_cdef_block(PyrexScanner s, ctx)
|
| 179 |
+
cdef p_cdef_extern_block(PyrexScanner s, pos, ctx)
|
| 180 |
+
cdef p_c_enum_definition(PyrexScanner s, pos, ctx)
|
| 181 |
+
cdef p_c_enum_line(PyrexScanner s, ctx, list items)
|
| 182 |
+
cdef p_c_enum_item(PyrexScanner s, ctx, list items)
|
| 183 |
+
cdef p_c_struct_or_union_definition(PyrexScanner s, pos, ctx)
|
| 184 |
+
cdef p_fused_definition(PyrexScanner s, pos, ctx)
|
| 185 |
+
cdef p_struct_enum(PyrexScanner s, pos, ctx)
|
| 186 |
+
cdef p_visibility(PyrexScanner s, prev_visibility)
|
| 187 |
+
cdef p_c_modifiers(PyrexScanner s)
|
| 188 |
+
cdef p_c_func_or_var_declaration(PyrexScanner s, pos, ctx)
|
| 189 |
+
cdef p_ctypedef_statement(PyrexScanner s, ctx)
|
| 190 |
+
cdef p_decorators(PyrexScanner s)
|
| 191 |
+
cdef _reject_cdef_modifier_in_py(PyrexScanner s, name)
|
| 192 |
+
cdef p_def_statement(PyrexScanner s, list decorators=*, bint is_async_def=*)
|
| 193 |
+
cdef p_varargslist(PyrexScanner s, terminator=*, bint annotated = *)
|
| 194 |
+
cdef p_py_arg_decl(PyrexScanner s, bint annotated = *)
|
| 195 |
+
cdef p_class_statement(PyrexScanner s, decorators)
|
| 196 |
+
cdef p_c_class_definition(PyrexScanner s, pos, ctx)
|
| 197 |
+
cdef tuple p_c_class_options(PyrexScanner s)
|
| 198 |
+
cdef p_property_decl(PyrexScanner s)
|
| 199 |
+
cdef p_doc_string(PyrexScanner s)
|
| 200 |
+
cdef p_ignorable_statement(PyrexScanner s)
|
| 201 |
+
cdef dict p_compiler_directive_comments(PyrexScanner s)
|
| 202 |
+
cdef p_template_definition(PyrexScanner s)
|
| 203 |
+
cdef p_cpp_class_definition(PyrexScanner s, pos, ctx)
|
| 204 |
+
cdef p_cpp_class_attribute(PyrexScanner s, ctx)
|
| 205 |
+
cdef p_annotation(PyrexScanner s)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Pipeline.py
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import itertools
|
| 4 |
+
from time import time
|
| 5 |
+
|
| 6 |
+
from . import Errors
|
| 7 |
+
from . import DebugFlags
|
| 8 |
+
from . import Options
|
| 9 |
+
from .Errors import CompileError, InternalError, AbortError
|
| 10 |
+
from . import Naming
|
| 11 |
+
|
| 12 |
+
#
|
| 13 |
+
# Really small pipeline stages
|
| 14 |
+
#
|
| 15 |
+
def dumptree(t):
|
| 16 |
+
# For quick debugging in pipelines
|
| 17 |
+
print(t.dump())
|
| 18 |
+
return t
|
| 19 |
+
|
| 20 |
+
def abort_on_errors(node):
|
| 21 |
+
# Stop the pipeline if there are any errors.
|
| 22 |
+
if Errors.get_errors_count() != 0:
|
| 23 |
+
raise AbortError("pipeline break")
|
| 24 |
+
return node
|
| 25 |
+
|
| 26 |
+
def parse_stage_factory(context):
|
| 27 |
+
def parse(compsrc):
|
| 28 |
+
source_desc = compsrc.source_desc
|
| 29 |
+
full_module_name = compsrc.full_module_name
|
| 30 |
+
initial_pos = (source_desc, 1, 0)
|
| 31 |
+
saved_cimport_from_pyx, Options.cimport_from_pyx = Options.cimport_from_pyx, False
|
| 32 |
+
scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0)
|
| 33 |
+
Options.cimport_from_pyx = saved_cimport_from_pyx
|
| 34 |
+
tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
|
| 35 |
+
tree.compilation_source = compsrc
|
| 36 |
+
tree.scope = scope
|
| 37 |
+
tree.is_pxd = False
|
| 38 |
+
return tree
|
| 39 |
+
return parse
|
| 40 |
+
|
| 41 |
+
def parse_pxd_stage_factory(context, scope, module_name):
|
| 42 |
+
def parse(source_desc):
|
| 43 |
+
tree = context.parse(source_desc, scope, pxd=True,
|
| 44 |
+
full_module_name=module_name)
|
| 45 |
+
tree.scope = scope
|
| 46 |
+
tree.is_pxd = True
|
| 47 |
+
return tree
|
| 48 |
+
return parse
|
| 49 |
+
|
| 50 |
+
def generate_pyx_code_stage_factory(options, result):
|
| 51 |
+
def generate_pyx_code_stage(module_node):
|
| 52 |
+
module_node.process_implementation(options, result)
|
| 53 |
+
result.compilation_source = module_node.compilation_source
|
| 54 |
+
return result
|
| 55 |
+
return generate_pyx_code_stage
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def inject_pxd_code_stage_factory(context):
|
| 59 |
+
def inject_pxd_code_stage(module_node):
|
| 60 |
+
for name, (statlistnode, scope) in context.pxds.items():
|
| 61 |
+
module_node.merge_in(statlistnode, scope, stage="pxd")
|
| 62 |
+
return module_node
|
| 63 |
+
return inject_pxd_code_stage
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def use_utility_code_definitions(scope, target, seen=None):
|
| 67 |
+
if seen is None:
|
| 68 |
+
seen = set()
|
| 69 |
+
|
| 70 |
+
for entry in scope.entries.values():
|
| 71 |
+
if entry in seen:
|
| 72 |
+
continue
|
| 73 |
+
|
| 74 |
+
seen.add(entry)
|
| 75 |
+
if entry.used and entry.utility_code_definition:
|
| 76 |
+
target.use_utility_code(entry.utility_code_definition)
|
| 77 |
+
for required_utility in entry.utility_code_definition.requires:
|
| 78 |
+
target.use_utility_code(required_utility)
|
| 79 |
+
elif entry.as_module:
|
| 80 |
+
use_utility_code_definitions(entry.as_module, target, seen)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def sorted_utility_codes_and_deps(utilcodes):
|
| 84 |
+
ranks = {}
|
| 85 |
+
get_rank = ranks.get
|
| 86 |
+
|
| 87 |
+
def calculate_rank(utilcode):
|
| 88 |
+
rank = get_rank(utilcode)
|
| 89 |
+
if rank is None:
|
| 90 |
+
ranks[utilcode] = 0 # prevent infinite recursion on circular dependencies
|
| 91 |
+
original_order = len(ranks)
|
| 92 |
+
rank = ranks[utilcode] = 1 + (
|
| 93 |
+
min([calculate_rank(dep) for dep in utilcode.requires]) if utilcode.requires else -1
|
| 94 |
+
) + original_order * 1e-8
|
| 95 |
+
return rank
|
| 96 |
+
|
| 97 |
+
for utilcode in utilcodes:
|
| 98 |
+
calculate_rank(utilcode)
|
| 99 |
+
|
| 100 |
+
# include all recursively collected dependencies
|
| 101 |
+
return sorted(ranks, key=get_rank)
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def normalize_deps(utilcodes):
|
| 105 |
+
deps = {utilcode:utilcode for utilcode in utilcodes}
|
| 106 |
+
for utilcode in utilcodes:
|
| 107 |
+
utilcode.requires = [deps.setdefault(dep, dep) for dep in utilcode.requires or ()]
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def inject_utility_code_stage_factory(context):
|
| 111 |
+
def inject_utility_code_stage(module_node):
|
| 112 |
+
module_node.prepare_utility_code()
|
| 113 |
+
use_utility_code_definitions(context.cython_scope, module_node.scope)
|
| 114 |
+
|
| 115 |
+
utility_code_list = module_node.scope.utility_code_list
|
| 116 |
+
utility_code_list[:] = sorted_utility_codes_and_deps(utility_code_list)
|
| 117 |
+
normalize_deps(utility_code_list)
|
| 118 |
+
|
| 119 |
+
added = set()
|
| 120 |
+
# Note: the list might be extended inside the loop (if some utility code
|
| 121 |
+
# pulls in other utility code, explicitly or implicitly)
|
| 122 |
+
for utilcode in utility_code_list:
|
| 123 |
+
if utilcode in added:
|
| 124 |
+
continue
|
| 125 |
+
added.add(utilcode)
|
| 126 |
+
if utilcode.requires:
|
| 127 |
+
for dep in utilcode.requires:
|
| 128 |
+
if dep not in added:
|
| 129 |
+
utility_code_list.append(dep)
|
| 130 |
+
tree = utilcode.get_tree(cython_scope=context.cython_scope)
|
| 131 |
+
if tree:
|
| 132 |
+
module_node.merge_in(tree.with_compiler_directives(),
|
| 133 |
+
tree.scope, stage="utility",
|
| 134 |
+
merge_scope=True)
|
| 135 |
+
return module_node
|
| 136 |
+
|
| 137 |
+
return inject_utility_code_stage
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
#
|
| 141 |
+
# Pipeline factories
|
| 142 |
+
#
|
| 143 |
+
|
| 144 |
+
def create_pipeline(context, mode, exclude_classes=()):
|
| 145 |
+
assert mode in ('pyx', 'py', 'pxd')
|
| 146 |
+
from .Visitor import PrintTree
|
| 147 |
+
from .ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse
|
| 148 |
+
from .ParseTreeTransforms import ForwardDeclareTypes, InjectGilHandling, AnalyseDeclarationsTransform
|
| 149 |
+
from .ParseTreeTransforms import AnalyseExpressionsTransform, FindInvalidUseOfFusedTypes
|
| 150 |
+
from .ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
|
| 151 |
+
from .ParseTreeTransforms import TrackNumpyAttributes, InterpretCompilerDirectives, TransformBuiltinMethods
|
| 152 |
+
from .ParseTreeTransforms import ExpandInplaceOperators, ParallelRangeTransform
|
| 153 |
+
from .ParseTreeTransforms import CalculateQualifiedNamesTransform
|
| 154 |
+
from .TypeInference import MarkParallelAssignments, MarkOverflowingArithmetic
|
| 155 |
+
from .ParseTreeTransforms import AdjustDefByDirectives, AlignFunctionDefinitions, AutoCpdefFunctionDefinitions
|
| 156 |
+
from .ParseTreeTransforms import RemoveUnreachableCode, GilCheck, CoerceCppTemps
|
| 157 |
+
from .FlowControl import ControlFlowAnalysis
|
| 158 |
+
from .AnalysedTreeTransforms import AutoTestDictTransform
|
| 159 |
+
from .AutoDocTransforms import EmbedSignature
|
| 160 |
+
from .Optimize import FlattenInListTransform, SwitchTransform, IterationTransform
|
| 161 |
+
from .Optimize import EarlyReplaceBuiltinCalls, OptimizeBuiltinCalls
|
| 162 |
+
from .Optimize import InlineDefNodeCalls
|
| 163 |
+
from .Optimize import ConstantFolding, FinalOptimizePhase
|
| 164 |
+
from .Optimize import DropRefcountingTransform
|
| 165 |
+
from .Optimize import ConsolidateOverflowCheck
|
| 166 |
+
from .Buffer import IntroduceBufferAuxiliaryVars
|
| 167 |
+
from .ModuleNode import check_c_declarations, check_c_declarations_pxd
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
if mode == 'pxd':
|
| 171 |
+
_check_c_declarations = check_c_declarations_pxd
|
| 172 |
+
_specific_post_parse = PxdPostParse(context)
|
| 173 |
+
else:
|
| 174 |
+
_check_c_declarations = check_c_declarations
|
| 175 |
+
_specific_post_parse = None
|
| 176 |
+
|
| 177 |
+
if mode == 'py':
|
| 178 |
+
_align_function_definitions = AlignFunctionDefinitions(context)
|
| 179 |
+
else:
|
| 180 |
+
_align_function_definitions = None
|
| 181 |
+
|
| 182 |
+
# NOTE: This is the "common" parts of the pipeline, which is also
|
| 183 |
+
# code in pxd files. So it will be run multiple times in a
|
| 184 |
+
# compilation stage.
|
| 185 |
+
stages = [
|
| 186 |
+
NormalizeTree(context),
|
| 187 |
+
PostParse(context),
|
| 188 |
+
_specific_post_parse,
|
| 189 |
+
TrackNumpyAttributes(),
|
| 190 |
+
InterpretCompilerDirectives(context, context.compiler_directives),
|
| 191 |
+
ParallelRangeTransform(context),
|
| 192 |
+
WithTransform(),
|
| 193 |
+
AdjustDefByDirectives(context),
|
| 194 |
+
_align_function_definitions,
|
| 195 |
+
MarkClosureVisitor(context),
|
| 196 |
+
AutoCpdefFunctionDefinitions(context),
|
| 197 |
+
RemoveUnreachableCode(context),
|
| 198 |
+
ConstantFolding(),
|
| 199 |
+
FlattenInListTransform(),
|
| 200 |
+
DecoratorTransform(context),
|
| 201 |
+
ForwardDeclareTypes(context),
|
| 202 |
+
InjectGilHandling(),
|
| 203 |
+
AnalyseDeclarationsTransform(context),
|
| 204 |
+
AutoTestDictTransform(context),
|
| 205 |
+
EmbedSignature(context),
|
| 206 |
+
EarlyReplaceBuiltinCalls(context), ## Necessary?
|
| 207 |
+
TransformBuiltinMethods(context),
|
| 208 |
+
MarkParallelAssignments(context),
|
| 209 |
+
ControlFlowAnalysis(context),
|
| 210 |
+
RemoveUnreachableCode(context),
|
| 211 |
+
# MarkParallelAssignments(context),
|
| 212 |
+
MarkOverflowingArithmetic(context),
|
| 213 |
+
IntroduceBufferAuxiliaryVars(context),
|
| 214 |
+
_check_c_declarations,
|
| 215 |
+
InlineDefNodeCalls(context),
|
| 216 |
+
AnalyseExpressionsTransform(context),
|
| 217 |
+
FindInvalidUseOfFusedTypes(context),
|
| 218 |
+
ExpandInplaceOperators(context),
|
| 219 |
+
IterationTransform(context),
|
| 220 |
+
SwitchTransform(context),
|
| 221 |
+
OptimizeBuiltinCalls(context), ## Necessary?
|
| 222 |
+
CreateClosureClasses(context), ## After all lookups and type inference
|
| 223 |
+
CalculateQualifiedNamesTransform(context),
|
| 224 |
+
ConsolidateOverflowCheck(context),
|
| 225 |
+
DropRefcountingTransform(),
|
| 226 |
+
FinalOptimizePhase(context),
|
| 227 |
+
CoerceCppTemps(context),
|
| 228 |
+
GilCheck(),
|
| 229 |
+
]
|
| 230 |
+
if exclude_classes:
|
| 231 |
+
stages = [s for s in stages if s.__class__ not in exclude_classes]
|
| 232 |
+
return stages
|
| 233 |
+
|
| 234 |
+
def create_pyx_pipeline(context, options, result, py=False, exclude_classes=()):
|
| 235 |
+
mode = 'py' if py else 'pyx'
|
| 236 |
+
|
| 237 |
+
test_support = []
|
| 238 |
+
ctest_support = []
|
| 239 |
+
if options.evaluate_tree_assertions:
|
| 240 |
+
from ..TestUtils import TreeAssertVisitor
|
| 241 |
+
test_validator = TreeAssertVisitor()
|
| 242 |
+
test_support.append(test_validator)
|
| 243 |
+
ctest_support.append(test_validator.create_c_file_validator())
|
| 244 |
+
|
| 245 |
+
if options.gdb_debug:
|
| 246 |
+
from ..Debugger import DebugWriter # requires Py2.5+
|
| 247 |
+
from .ParseTreeTransforms import DebugTransform
|
| 248 |
+
context.gdb_debug_outputwriter = DebugWriter.CythonDebugWriter(
|
| 249 |
+
options.output_dir)
|
| 250 |
+
debug_transform = [DebugTransform(context, options, result)]
|
| 251 |
+
else:
|
| 252 |
+
debug_transform = []
|
| 253 |
+
|
| 254 |
+
return list(itertools.chain(
|
| 255 |
+
[parse_stage_factory(context)],
|
| 256 |
+
create_pipeline(context, mode, exclude_classes=exclude_classes),
|
| 257 |
+
test_support,
|
| 258 |
+
[inject_pxd_code_stage_factory(context),
|
| 259 |
+
inject_utility_code_stage_factory(context),
|
| 260 |
+
abort_on_errors],
|
| 261 |
+
debug_transform,
|
| 262 |
+
[generate_pyx_code_stage_factory(options, result)],
|
| 263 |
+
ctest_support,
|
| 264 |
+
))
|
| 265 |
+
|
| 266 |
+
def create_pxd_pipeline(context, scope, module_name):
|
| 267 |
+
from .CodeGeneration import ExtractPxdCode
|
| 268 |
+
|
| 269 |
+
# The pxd pipeline ends up with a CCodeWriter containing the
|
| 270 |
+
# code of the pxd, as well as a pxd scope.
|
| 271 |
+
return [
|
| 272 |
+
parse_pxd_stage_factory(context, scope, module_name)
|
| 273 |
+
] + create_pipeline(context, 'pxd') + [
|
| 274 |
+
ExtractPxdCode()
|
| 275 |
+
]
|
| 276 |
+
|
| 277 |
+
def create_py_pipeline(context, options, result):
|
| 278 |
+
return create_pyx_pipeline(context, options, result, py=True)
|
| 279 |
+
|
| 280 |
+
def create_pyx_as_pxd_pipeline(context, result):
|
| 281 |
+
from .ParseTreeTransforms import AlignFunctionDefinitions, \
|
| 282 |
+
MarkClosureVisitor, WithTransform, AnalyseDeclarationsTransform
|
| 283 |
+
from .Optimize import ConstantFolding, FlattenInListTransform
|
| 284 |
+
from .Nodes import StatListNode
|
| 285 |
+
pipeline = []
|
| 286 |
+
pyx_pipeline = create_pyx_pipeline(context, context.options, result,
|
| 287 |
+
exclude_classes=[
|
| 288 |
+
AlignFunctionDefinitions,
|
| 289 |
+
MarkClosureVisitor,
|
| 290 |
+
ConstantFolding,
|
| 291 |
+
FlattenInListTransform,
|
| 292 |
+
WithTransform
|
| 293 |
+
])
|
| 294 |
+
from .Visitor import VisitorTransform
|
| 295 |
+
class SetInPxdTransform(VisitorTransform):
|
| 296 |
+
# A number of nodes have an "in_pxd" attribute which affects AnalyseDeclarationsTransform
|
| 297 |
+
# (for example controlling pickling generation). Set it, to make sure we don't mix them up with
|
| 298 |
+
# the importing main module.
|
| 299 |
+
# FIXME: This should be done closer to the parsing step.
|
| 300 |
+
def visit_StatNode(self, node):
|
| 301 |
+
if hasattr(node, "in_pxd"):
|
| 302 |
+
node.in_pxd = True
|
| 303 |
+
self.visitchildren(node)
|
| 304 |
+
return node
|
| 305 |
+
|
| 306 |
+
visit_Node = VisitorTransform.recurse_to_children
|
| 307 |
+
|
| 308 |
+
for stage in pyx_pipeline:
|
| 309 |
+
pipeline.append(stage)
|
| 310 |
+
if isinstance(stage, AnalyseDeclarationsTransform):
|
| 311 |
+
pipeline.insert(-1, SetInPxdTransform())
|
| 312 |
+
break # This is the last stage we need.
|
| 313 |
+
def fake_pxd(root):
|
| 314 |
+
for entry in root.scope.entries.values():
|
| 315 |
+
if not entry.in_cinclude:
|
| 316 |
+
entry.defined_in_pxd = 1
|
| 317 |
+
if entry.name == entry.cname and entry.visibility != 'extern':
|
| 318 |
+
# Always mangle non-extern cimported entries.
|
| 319 |
+
entry.cname = entry.scope.mangle(Naming.func_prefix, entry.name)
|
| 320 |
+
return StatListNode(root.pos, stats=[]), root.scope
|
| 321 |
+
pipeline.append(fake_pxd)
|
| 322 |
+
return pipeline
|
| 323 |
+
|
| 324 |
+
def insert_into_pipeline(pipeline, transform, before=None, after=None):
|
| 325 |
+
"""
|
| 326 |
+
Insert a new transform into the pipeline after or before an instance of
|
| 327 |
+
the given class. e.g.
|
| 328 |
+
|
| 329 |
+
pipeline = insert_into_pipeline(pipeline, transform,
|
| 330 |
+
after=AnalyseDeclarationsTransform)
|
| 331 |
+
"""
|
| 332 |
+
assert before or after
|
| 333 |
+
|
| 334 |
+
cls = before or after
|
| 335 |
+
for i, t in enumerate(pipeline):
|
| 336 |
+
if isinstance(t, cls):
|
| 337 |
+
break
|
| 338 |
+
|
| 339 |
+
if after:
|
| 340 |
+
i += 1
|
| 341 |
+
|
| 342 |
+
return pipeline[:i] + [transform] + pipeline[i:]
|
| 343 |
+
|
| 344 |
+
#
|
| 345 |
+
# Running a pipeline
|
| 346 |
+
#
|
| 347 |
+
|
| 348 |
+
_pipeline_entry_points = {}
|
| 349 |
+
|
| 350 |
+
try:
|
| 351 |
+
from threading import local as _threadlocal
|
| 352 |
+
except ImportError:
|
| 353 |
+
class _threadlocal(object): pass
|
| 354 |
+
|
| 355 |
+
threadlocal = _threadlocal()
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
def get_timings():
|
| 359 |
+
try:
|
| 360 |
+
return threadlocal.cython_pipeline_timings
|
| 361 |
+
except AttributeError:
|
| 362 |
+
return {}
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
def run_pipeline(pipeline, source, printtree=True):
|
| 366 |
+
from .Visitor import PrintTree
|
| 367 |
+
exec_ns = globals().copy() if DebugFlags.debug_verbose_pipeline else None
|
| 368 |
+
|
| 369 |
+
try:
|
| 370 |
+
timings = threadlocal.cython_pipeline_timings
|
| 371 |
+
except AttributeError:
|
| 372 |
+
timings = threadlocal.cython_pipeline_timings = {}
|
| 373 |
+
|
| 374 |
+
def run(phase, data):
|
| 375 |
+
return phase(data)
|
| 376 |
+
|
| 377 |
+
error = None
|
| 378 |
+
data = source
|
| 379 |
+
try:
|
| 380 |
+
try:
|
| 381 |
+
for phase in pipeline:
|
| 382 |
+
if phase is None:
|
| 383 |
+
continue
|
| 384 |
+
if not printtree and isinstance(phase, PrintTree):
|
| 385 |
+
continue
|
| 386 |
+
|
| 387 |
+
phase_name = getattr(phase, '__name__', type(phase).__name__)
|
| 388 |
+
if DebugFlags.debug_verbose_pipeline:
|
| 389 |
+
print("Entering pipeline phase %r" % phase)
|
| 390 |
+
# create a new wrapper for each step to show the name in profiles
|
| 391 |
+
try:
|
| 392 |
+
run = _pipeline_entry_points[phase_name]
|
| 393 |
+
except KeyError:
|
| 394 |
+
exec("def %s(phase, data): return phase(data)" % phase_name, exec_ns)
|
| 395 |
+
run = _pipeline_entry_points[phase_name] = exec_ns[phase_name]
|
| 396 |
+
|
| 397 |
+
t = time()
|
| 398 |
+
data = run(phase, data)
|
| 399 |
+
t = time() - t
|
| 400 |
+
|
| 401 |
+
try:
|
| 402 |
+
old_t, count = timings[phase_name]
|
| 403 |
+
except KeyError:
|
| 404 |
+
old_t, count = 0, 0
|
| 405 |
+
timings[phase_name] = (old_t + int(t * 1000000), count + 1)
|
| 406 |
+
if DebugFlags.debug_verbose_pipeline:
|
| 407 |
+
print(" %.3f seconds" % t)
|
| 408 |
+
except CompileError as err:
|
| 409 |
+
# err is set
|
| 410 |
+
Errors.report_error(err, use_stack=False)
|
| 411 |
+
error = err
|
| 412 |
+
except InternalError as err:
|
| 413 |
+
# Only raise if there was not an earlier error
|
| 414 |
+
if Errors.get_errors_count() == 0:
|
| 415 |
+
raise
|
| 416 |
+
error = err
|
| 417 |
+
except AbortError as err:
|
| 418 |
+
error = err
|
| 419 |
+
return (error, data)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Scanning.pxd
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: language_level=3
|
| 2 |
+
|
| 3 |
+
import cython
|
| 4 |
+
|
| 5 |
+
from ..Plex.Scanners cimport Scanner
|
| 6 |
+
|
| 7 |
+
cdef unicode any_string_prefix, IDENT
|
| 8 |
+
|
| 9 |
+
cdef get_lexicon()
|
| 10 |
+
cdef initial_compile_time_env()
|
| 11 |
+
|
| 12 |
+
## methods commented with '##' out are used by Parsing.py when compiled.
|
| 13 |
+
|
| 14 |
+
@cython.final
|
| 15 |
+
cdef class CompileTimeScope:
|
| 16 |
+
cdef public dict entries
|
| 17 |
+
cdef public CompileTimeScope outer
|
| 18 |
+
##cdef declare(self, name, value)
|
| 19 |
+
##cdef lookup_here(self, name)
|
| 20 |
+
##cpdef lookup(self, name)
|
| 21 |
+
|
| 22 |
+
@cython.final
|
| 23 |
+
cdef class PyrexScanner(Scanner):
|
| 24 |
+
cdef public context
|
| 25 |
+
cdef public list included_files
|
| 26 |
+
cdef public CompileTimeScope compile_time_env
|
| 27 |
+
cdef public bint compile_time_eval
|
| 28 |
+
cdef public bint compile_time_expr
|
| 29 |
+
cdef public bint parse_comments
|
| 30 |
+
cdef public bint in_python_file
|
| 31 |
+
cdef public source_encoding
|
| 32 |
+
cdef dict keywords
|
| 33 |
+
cdef public list indentation_stack
|
| 34 |
+
cdef public indentation_char
|
| 35 |
+
cdef public int bracket_nesting_level
|
| 36 |
+
cdef readonly bint async_enabled
|
| 37 |
+
cdef public unicode sy
|
| 38 |
+
cdef public systring # EncodedString
|
| 39 |
+
cdef public list put_back_on_failure
|
| 40 |
+
|
| 41 |
+
cdef Py_ssize_t current_level(self)
|
| 42 |
+
#cpdef commentline(self, text)
|
| 43 |
+
#cpdef open_bracket_action(self, text)
|
| 44 |
+
#cpdef close_bracket_action(self, text)
|
| 45 |
+
#cpdef newline_action(self, text)
|
| 46 |
+
#cpdef begin_string_action(self, text)
|
| 47 |
+
#cpdef end_string_action(self, text)
|
| 48 |
+
#cpdef unclosed_string_action(self, text)
|
| 49 |
+
@cython.locals(current_level=Py_ssize_t, new_level=Py_ssize_t)
|
| 50 |
+
cpdef indentation_action(self, text)
|
| 51 |
+
#cpdef eof_action(self, text)
|
| 52 |
+
##cdef next(self)
|
| 53 |
+
##cdef peek(self)
|
| 54 |
+
#cpdef put_back(self, sy, systring)
|
| 55 |
+
##cdef bint expect(self, what, message = *) except -2
|
| 56 |
+
##cdef expect_keyword(self, what, message = *)
|
| 57 |
+
##cdef expected(self, what, message = *)
|
| 58 |
+
##cdef expect_indent(self)
|
| 59 |
+
##cdef expect_dedent(self)
|
| 60 |
+
##cdef expect_newline(self, message=*, bint ignore_semicolon=*)
|
| 61 |
+
##cdef int enter_async(self) except -1
|
| 62 |
+
##cdef int exit_async(self) except -1
|
| 63 |
+
cdef void error_at_scanpos(self, str message) except *
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/TestGrammar.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# mode: run
|
| 2 |
+
# tag: syntax
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
Uses TreeFragment to test invalid syntax.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import absolute_import
|
| 9 |
+
|
| 10 |
+
import ast
|
| 11 |
+
import textwrap
|
| 12 |
+
|
| 13 |
+
from ...TestUtils import CythonTest
|
| 14 |
+
from .. import ExprNodes
|
| 15 |
+
from ..Errors import CompileError
|
| 16 |
+
|
| 17 |
+
# Copied from CPython's test_grammar.py
|
| 18 |
+
VALID_UNDERSCORE_LITERALS = [
|
| 19 |
+
'0_0_0',
|
| 20 |
+
'4_2',
|
| 21 |
+
'1_0000_0000',
|
| 22 |
+
'0b1001_0100',
|
| 23 |
+
'0xffff_ffff',
|
| 24 |
+
'0o5_7_7',
|
| 25 |
+
'1_00_00.5',
|
| 26 |
+
'1_00_00.5j',
|
| 27 |
+
'1_00_00.5e5',
|
| 28 |
+
'1_00_00j',
|
| 29 |
+
'1_00_00e5_1',
|
| 30 |
+
'1e1_0',
|
| 31 |
+
'.1_4',
|
| 32 |
+
'.1_4e1',
|
| 33 |
+
'0b_0',
|
| 34 |
+
'0x_f',
|
| 35 |
+
'0o_5',
|
| 36 |
+
'1_00_00j',
|
| 37 |
+
'1_00_00.5j',
|
| 38 |
+
'1_00_00e5_1j',
|
| 39 |
+
'.1_4j',
|
| 40 |
+
'(1_2.5+3_3j)',
|
| 41 |
+
'(.5_6j)',
|
| 42 |
+
]
|
| 43 |
+
|
| 44 |
+
# Copied from CPython's test_grammar.py
|
| 45 |
+
INVALID_UNDERSCORE_LITERALS = [
|
| 46 |
+
# Trailing underscores:
|
| 47 |
+
'0_',
|
| 48 |
+
'42_',
|
| 49 |
+
'1.4j_',
|
| 50 |
+
'0x_',
|
| 51 |
+
'0b1_',
|
| 52 |
+
'0xf_',
|
| 53 |
+
'0o5_',
|
| 54 |
+
'0 if 1_Else 1',
|
| 55 |
+
# Underscores in the base selector:
|
| 56 |
+
'0_b0',
|
| 57 |
+
'0_xf',
|
| 58 |
+
'0_o5',
|
| 59 |
+
# Old-style octal, still disallowed:
|
| 60 |
+
# FIXME: still need to support PY_VERSION_HEX < 3
|
| 61 |
+
'0_7',
|
| 62 |
+
'09_99',
|
| 63 |
+
# Multiple consecutive underscores:
|
| 64 |
+
'4_______2',
|
| 65 |
+
'0.1__4',
|
| 66 |
+
'0.1__4j',
|
| 67 |
+
'0b1001__0100',
|
| 68 |
+
'0xffff__ffff',
|
| 69 |
+
'0x___',
|
| 70 |
+
'0o5__77',
|
| 71 |
+
'1e1__0',
|
| 72 |
+
'1e1__0j',
|
| 73 |
+
# Underscore right before a dot:
|
| 74 |
+
'1_.4',
|
| 75 |
+
'1_.4j',
|
| 76 |
+
# Underscore right after a dot:
|
| 77 |
+
'1._4',
|
| 78 |
+
'1._4j',
|
| 79 |
+
'._5',
|
| 80 |
+
'._5j',
|
| 81 |
+
# Underscore right after a sign:
|
| 82 |
+
'1.0e+_1',
|
| 83 |
+
'1.0e+_1j',
|
| 84 |
+
# Underscore right before j:
|
| 85 |
+
'1.4_j',
|
| 86 |
+
'1.4e5_j',
|
| 87 |
+
# Underscore right before e:
|
| 88 |
+
'1_e1',
|
| 89 |
+
'1.4_e1',
|
| 90 |
+
'1.4_e1j',
|
| 91 |
+
# Underscore right after e:
|
| 92 |
+
'1e_1',
|
| 93 |
+
'1.4e_1',
|
| 94 |
+
'1.4e_1j',
|
| 95 |
+
# Complex cases with parens:
|
| 96 |
+
'(1+1.5_j_)',
|
| 97 |
+
'(1+1.5_j)',
|
| 98 |
+
# Whitespace in literals
|
| 99 |
+
'1_ 2',
|
| 100 |
+
'1 _2',
|
| 101 |
+
'1_2.2_ 1',
|
| 102 |
+
'1_2.2 _1',
|
| 103 |
+
'1_2e _1',
|
| 104 |
+
'1_2e2 _1',
|
| 105 |
+
'1_2e 2_1',
|
| 106 |
+
]
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
INVALID_ELLIPSIS = [
|
| 110 |
+
(". . .", 2, 0),
|
| 111 |
+
(". ..", 2, 0),
|
| 112 |
+
(".. .", 2, 0),
|
| 113 |
+
(". ...", 2, 0),
|
| 114 |
+
(". ... .", 2, 0),
|
| 115 |
+
(".. ... .", 2, 0),
|
| 116 |
+
(". ... ..", 2, 0),
|
| 117 |
+
("""
|
| 118 |
+
(
|
| 119 |
+
.
|
| 120 |
+
..
|
| 121 |
+
)
|
| 122 |
+
""", 3, 4),
|
| 123 |
+
("""
|
| 124 |
+
[
|
| 125 |
+
..
|
| 126 |
+
.,
|
| 127 |
+
None
|
| 128 |
+
]
|
| 129 |
+
""", 3, 4),
|
| 130 |
+
("""
|
| 131 |
+
{
|
| 132 |
+
None,
|
| 133 |
+
.
|
| 134 |
+
.
|
| 135 |
+
|
| 136 |
+
.
|
| 137 |
+
}
|
| 138 |
+
""", 4, 4)
|
| 139 |
+
]
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
class TestGrammar(CythonTest):
|
| 143 |
+
|
| 144 |
+
def test_invalid_number_literals(self):
|
| 145 |
+
for literal in INVALID_UNDERSCORE_LITERALS:
|
| 146 |
+
for expression in ['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']:
|
| 147 |
+
code = 'x = ' + expression % literal
|
| 148 |
+
try:
|
| 149 |
+
self.fragment(u'''\
|
| 150 |
+
# cython: language_level=3
|
| 151 |
+
''' + code)
|
| 152 |
+
except CompileError as exc:
|
| 153 |
+
assert code in [s.strip() for s in str(exc).splitlines()], str(exc)
|
| 154 |
+
else:
|
| 155 |
+
assert False, "Invalid Cython code '%s' failed to raise an exception" % code
|
| 156 |
+
|
| 157 |
+
def test_valid_number_literals(self):
|
| 158 |
+
for literal in VALID_UNDERSCORE_LITERALS:
|
| 159 |
+
for i, expression in enumerate(['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']):
|
| 160 |
+
code = 'x = ' + expression % literal
|
| 161 |
+
node = self.fragment(u'''\
|
| 162 |
+
# cython: language_level=3
|
| 163 |
+
''' + code).root
|
| 164 |
+
assert node is not None
|
| 165 |
+
|
| 166 |
+
literal_node = node.stats[0].rhs # StatListNode([SingleAssignmentNode('x', expr)])
|
| 167 |
+
if i > 0:
|
| 168 |
+
# Add/MulNode() -> literal is first or second operand
|
| 169 |
+
literal_node = literal_node.operand2 if i % 2 else literal_node.operand1
|
| 170 |
+
if 'j' in literal or 'J' in literal:
|
| 171 |
+
if '+' in literal:
|
| 172 |
+
# FIXME: tighten this test
|
| 173 |
+
assert isinstance(literal_node, ExprNodes.AddNode), (literal, literal_node)
|
| 174 |
+
else:
|
| 175 |
+
assert isinstance(literal_node, ExprNodes.ImagNode), (literal, literal_node)
|
| 176 |
+
elif '.' in literal or 'e' in literal or 'E' in literal and not ('0x' in literal or '0X' in literal):
|
| 177 |
+
assert isinstance(literal_node, ExprNodes.FloatNode), (literal, literal_node)
|
| 178 |
+
else:
|
| 179 |
+
assert isinstance(literal_node, ExprNodes.IntNode), (literal, literal_node)
|
| 180 |
+
|
| 181 |
+
def test_invalid_ellipsis(self):
|
| 182 |
+
ERR = ":{0}:{1}: Expected an identifier or literal"
|
| 183 |
+
for code, line, col in INVALID_ELLIPSIS:
|
| 184 |
+
try:
|
| 185 |
+
ast.parse(textwrap.dedent(code))
|
| 186 |
+
except SyntaxError as exc:
|
| 187 |
+
assert True
|
| 188 |
+
else:
|
| 189 |
+
assert False, "Invalid Python code '%s' failed to raise an exception" % code
|
| 190 |
+
|
| 191 |
+
try:
|
| 192 |
+
self.fragment(u'''\
|
| 193 |
+
# cython: language_level=3
|
| 194 |
+
''' + code)
|
| 195 |
+
except CompileError as exc:
|
| 196 |
+
assert ERR.format(line, col) in str(exc), str(exc)
|
| 197 |
+
else:
|
| 198 |
+
assert False, "Invalid Cython code '%s' failed to raise an exception" % code
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
if __name__ == "__main__":
|
| 202 |
+
import unittest
|
| 203 |
+
unittest.main()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/TreePath.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
A simple XPath-like language for tree traversal.
|
| 3 |
+
|
| 4 |
+
This works by creating a filter chain of generator functions. Each
|
| 5 |
+
function selects a part of the expression, e.g. a child node, a
|
| 6 |
+
specific descendant or a node that holds an attribute.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
from __future__ import absolute_import
|
| 10 |
+
|
| 11 |
+
import re
|
| 12 |
+
import operator
|
| 13 |
+
import sys
|
| 14 |
+
|
| 15 |
+
if sys.version_info[0] >= 3:
|
| 16 |
+
_unicode = str
|
| 17 |
+
else:
|
| 18 |
+
_unicode = unicode
|
| 19 |
+
|
| 20 |
+
path_tokenizer = re.compile(
|
| 21 |
+
r"("
|
| 22 |
+
r"'[^']*'|\"[^\"]*\"|"
|
| 23 |
+
r"//?|"
|
| 24 |
+
r"\(\)|"
|
| 25 |
+
r"==?|"
|
| 26 |
+
r"[/.*\[\]()@])|"
|
| 27 |
+
r"([^/\[\]()@=\s]+)|"
|
| 28 |
+
r"\s+"
|
| 29 |
+
).findall
|
| 30 |
+
|
| 31 |
+
def iterchildren(node, attr_name):
|
| 32 |
+
# returns an iterable of all child nodes of that name
|
| 33 |
+
child = getattr(node, attr_name)
|
| 34 |
+
if child is not None:
|
| 35 |
+
if type(child) is list:
|
| 36 |
+
return child
|
| 37 |
+
else:
|
| 38 |
+
return [child]
|
| 39 |
+
else:
|
| 40 |
+
return ()
|
| 41 |
+
|
| 42 |
+
def _get_first_or_none(it):
|
| 43 |
+
try:
|
| 44 |
+
try:
|
| 45 |
+
_next = it.next
|
| 46 |
+
except AttributeError:
|
| 47 |
+
return next(it)
|
| 48 |
+
else:
|
| 49 |
+
return _next()
|
| 50 |
+
except StopIteration:
|
| 51 |
+
return None
|
| 52 |
+
|
| 53 |
+
def type_name(node):
|
| 54 |
+
return node.__class__.__name__.split('.')[-1]
|
| 55 |
+
|
| 56 |
+
def parse_func(next, token):
|
| 57 |
+
name = token[1]
|
| 58 |
+
token = next()
|
| 59 |
+
if token[0] != '(':
|
| 60 |
+
raise ValueError("Expected '(' after function name '%s'" % name)
|
| 61 |
+
predicate = handle_predicate(next, token)
|
| 62 |
+
return name, predicate
|
| 63 |
+
|
| 64 |
+
def handle_func_not(next, token):
|
| 65 |
+
"""
|
| 66 |
+
not(...)
|
| 67 |
+
"""
|
| 68 |
+
name, predicate = parse_func(next, token)
|
| 69 |
+
|
| 70 |
+
def select(result):
|
| 71 |
+
for node in result:
|
| 72 |
+
if _get_first_or_none(predicate([node])) is None:
|
| 73 |
+
yield node
|
| 74 |
+
return select
|
| 75 |
+
|
| 76 |
+
def handle_name(next, token):
|
| 77 |
+
"""
|
| 78 |
+
/NodeName/
|
| 79 |
+
or
|
| 80 |
+
func(...)
|
| 81 |
+
"""
|
| 82 |
+
name = token[1]
|
| 83 |
+
if name in functions:
|
| 84 |
+
return functions[name](next, token)
|
| 85 |
+
def select(result):
|
| 86 |
+
for node in result:
|
| 87 |
+
for attr_name in node.child_attrs:
|
| 88 |
+
for child in iterchildren(node, attr_name):
|
| 89 |
+
if type_name(child) == name:
|
| 90 |
+
yield child
|
| 91 |
+
return select
|
| 92 |
+
|
| 93 |
+
def handle_star(next, token):
|
| 94 |
+
"""
|
| 95 |
+
/*/
|
| 96 |
+
"""
|
| 97 |
+
def select(result):
|
| 98 |
+
for node in result:
|
| 99 |
+
for name in node.child_attrs:
|
| 100 |
+
for child in iterchildren(node, name):
|
| 101 |
+
yield child
|
| 102 |
+
return select
|
| 103 |
+
|
| 104 |
+
def handle_dot(next, token):
|
| 105 |
+
"""
|
| 106 |
+
/./
|
| 107 |
+
"""
|
| 108 |
+
def select(result):
|
| 109 |
+
return result
|
| 110 |
+
return select
|
| 111 |
+
|
| 112 |
+
def handle_descendants(next, token):
|
| 113 |
+
"""
|
| 114 |
+
//...
|
| 115 |
+
"""
|
| 116 |
+
token = next()
|
| 117 |
+
if token[0] == "*":
|
| 118 |
+
def iter_recursive(node):
|
| 119 |
+
for name in node.child_attrs:
|
| 120 |
+
for child in iterchildren(node, name):
|
| 121 |
+
yield child
|
| 122 |
+
for c in iter_recursive(child):
|
| 123 |
+
yield c
|
| 124 |
+
elif not token[0]:
|
| 125 |
+
node_name = token[1]
|
| 126 |
+
def iter_recursive(node):
|
| 127 |
+
for name in node.child_attrs:
|
| 128 |
+
for child in iterchildren(node, name):
|
| 129 |
+
if type_name(child) == node_name:
|
| 130 |
+
yield child
|
| 131 |
+
for c in iter_recursive(child):
|
| 132 |
+
yield c
|
| 133 |
+
else:
|
| 134 |
+
raise ValueError("Expected node name after '//'")
|
| 135 |
+
|
| 136 |
+
def select(result):
|
| 137 |
+
for node in result:
|
| 138 |
+
for child in iter_recursive(node):
|
| 139 |
+
yield child
|
| 140 |
+
|
| 141 |
+
return select
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def handle_attribute(next, token):
|
| 145 |
+
token = next()
|
| 146 |
+
if token[0]:
|
| 147 |
+
raise ValueError("Expected attribute name")
|
| 148 |
+
name = token[1]
|
| 149 |
+
value = None
|
| 150 |
+
try:
|
| 151 |
+
token = next()
|
| 152 |
+
except StopIteration:
|
| 153 |
+
pass
|
| 154 |
+
else:
|
| 155 |
+
if token[0] == '=':
|
| 156 |
+
value = parse_path_value(next)
|
| 157 |
+
readattr = operator.attrgetter(name)
|
| 158 |
+
if value is None:
|
| 159 |
+
def select(result):
|
| 160 |
+
for node in result:
|
| 161 |
+
try:
|
| 162 |
+
attr_value = readattr(node)
|
| 163 |
+
except AttributeError:
|
| 164 |
+
continue
|
| 165 |
+
if attr_value is not None:
|
| 166 |
+
yield attr_value
|
| 167 |
+
else:
|
| 168 |
+
def select(result):
|
| 169 |
+
for node in result:
|
| 170 |
+
try:
|
| 171 |
+
attr_value = readattr(node)
|
| 172 |
+
except AttributeError:
|
| 173 |
+
continue
|
| 174 |
+
if attr_value == value:
|
| 175 |
+
yield attr_value
|
| 176 |
+
elif (isinstance(attr_value, bytes) and isinstance(value, _unicode) and
|
| 177 |
+
attr_value == value.encode()):
|
| 178 |
+
# allow a bytes-to-string comparison too
|
| 179 |
+
yield attr_value
|
| 180 |
+
|
| 181 |
+
return select
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def parse_path_value(next):
|
| 185 |
+
token = next()
|
| 186 |
+
value = token[0]
|
| 187 |
+
if value:
|
| 188 |
+
if value[:1] == "'" or value[:1] == '"':
|
| 189 |
+
return value[1:-1]
|
| 190 |
+
try:
|
| 191 |
+
return int(value)
|
| 192 |
+
except ValueError:
|
| 193 |
+
pass
|
| 194 |
+
elif token[1].isdigit():
|
| 195 |
+
return int(token[1])
|
| 196 |
+
else:
|
| 197 |
+
name = token[1].lower()
|
| 198 |
+
if name == 'true':
|
| 199 |
+
return True
|
| 200 |
+
elif name == 'false':
|
| 201 |
+
return False
|
| 202 |
+
raise ValueError("Invalid attribute predicate: '%s'" % value)
|
| 203 |
+
|
| 204 |
+
def handle_predicate(next, token):
|
| 205 |
+
token = next()
|
| 206 |
+
selector = []
|
| 207 |
+
while token[0] != ']':
|
| 208 |
+
selector.append( operations[token[0]](next, token) )
|
| 209 |
+
try:
|
| 210 |
+
token = next()
|
| 211 |
+
except StopIteration:
|
| 212 |
+
break
|
| 213 |
+
else:
|
| 214 |
+
if token[0] == "/":
|
| 215 |
+
token = next()
|
| 216 |
+
|
| 217 |
+
if not token[0] and token[1] == 'and':
|
| 218 |
+
return logical_and(selector, handle_predicate(next, token))
|
| 219 |
+
|
| 220 |
+
def select(result):
|
| 221 |
+
for node in result:
|
| 222 |
+
subresult = iter((node,))
|
| 223 |
+
for select in selector:
|
| 224 |
+
subresult = select(subresult)
|
| 225 |
+
predicate_result = _get_first_or_none(subresult)
|
| 226 |
+
if predicate_result is not None:
|
| 227 |
+
yield node
|
| 228 |
+
return select
|
| 229 |
+
|
| 230 |
+
def logical_and(lhs_selects, rhs_select):
|
| 231 |
+
def select(result):
|
| 232 |
+
for node in result:
|
| 233 |
+
subresult = iter((node,))
|
| 234 |
+
for select in lhs_selects:
|
| 235 |
+
subresult = select(subresult)
|
| 236 |
+
predicate_result = _get_first_or_none(subresult)
|
| 237 |
+
subresult = iter((node,))
|
| 238 |
+
if predicate_result is not None:
|
| 239 |
+
for result_node in rhs_select(subresult):
|
| 240 |
+
yield node
|
| 241 |
+
return select
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
operations = {
|
| 245 |
+
"@": handle_attribute,
|
| 246 |
+
"": handle_name,
|
| 247 |
+
"*": handle_star,
|
| 248 |
+
".": handle_dot,
|
| 249 |
+
"//": handle_descendants,
|
| 250 |
+
"[": handle_predicate,
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
functions = {
|
| 254 |
+
'not' : handle_func_not
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
def _build_path_iterator(path):
|
| 258 |
+
# parse pattern
|
| 259 |
+
stream = iter([ (special,text)
|
| 260 |
+
for (special,text) in path_tokenizer(path)
|
| 261 |
+
if special or text ])
|
| 262 |
+
try:
|
| 263 |
+
_next = stream.next
|
| 264 |
+
except AttributeError:
|
| 265 |
+
# Python 3
|
| 266 |
+
def _next():
|
| 267 |
+
return next(stream)
|
| 268 |
+
token = _next()
|
| 269 |
+
selector = []
|
| 270 |
+
while 1:
|
| 271 |
+
try:
|
| 272 |
+
selector.append(operations[token[0]](_next, token))
|
| 273 |
+
except StopIteration:
|
| 274 |
+
raise ValueError("invalid path")
|
| 275 |
+
try:
|
| 276 |
+
token = _next()
|
| 277 |
+
if token[0] == "/":
|
| 278 |
+
token = _next()
|
| 279 |
+
except StopIteration:
|
| 280 |
+
break
|
| 281 |
+
return selector
|
| 282 |
+
|
| 283 |
+
# main module API
|
| 284 |
+
|
| 285 |
+
def iterfind(node, path):
|
| 286 |
+
selector_chain = _build_path_iterator(path)
|
| 287 |
+
result = iter((node,))
|
| 288 |
+
for select in selector_chain:
|
| 289 |
+
result = select(result)
|
| 290 |
+
return result
|
| 291 |
+
|
| 292 |
+
def find_first(node, path):
|
| 293 |
+
return _get_first_or_none(iterfind(node, path))
|
| 294 |
+
|
| 295 |
+
def find_all(node, path):
|
| 296 |
+
return list(iterfind(node, path))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/TypeSlots.py
ADDED
|
@@ -0,0 +1,1180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# Tables describing slots in the CPython type object
|
| 3 |
+
# and associated know-how.
|
| 4 |
+
#
|
| 5 |
+
|
| 6 |
+
from __future__ import absolute_import
|
| 7 |
+
|
| 8 |
+
from . import Naming
|
| 9 |
+
from . import PyrexTypes
|
| 10 |
+
from .Errors import error
|
| 11 |
+
|
| 12 |
+
import copy
|
| 13 |
+
|
| 14 |
+
invisible = ['__cinit__', '__dealloc__', '__richcmp__',
|
| 15 |
+
'__nonzero__', '__bool__']
|
| 16 |
+
|
| 17 |
+
richcmp_special_methods = ['__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__']
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class Signature(object):
|
| 21 |
+
# Method slot signature descriptor.
|
| 22 |
+
#
|
| 23 |
+
# has_dummy_arg boolean
|
| 24 |
+
# has_generic_args boolean
|
| 25 |
+
# fixed_arg_format string
|
| 26 |
+
# ret_format string
|
| 27 |
+
# error_value string
|
| 28 |
+
# use_fastcall boolean
|
| 29 |
+
#
|
| 30 |
+
# The formats are strings made up of the following
|
| 31 |
+
# characters:
|
| 32 |
+
#
|
| 33 |
+
# 'O' Python object
|
| 34 |
+
# 'T' Python object of the type of 'self'
|
| 35 |
+
# 'v' void
|
| 36 |
+
# 'p' void *
|
| 37 |
+
# 'P' void **
|
| 38 |
+
# 'i' int
|
| 39 |
+
# 'b' bint
|
| 40 |
+
# 'I' int *
|
| 41 |
+
# 'l' long
|
| 42 |
+
# 'f' float
|
| 43 |
+
# 'd' double
|
| 44 |
+
# 'h' Py_hash_t
|
| 45 |
+
# 'z' Py_ssize_t
|
| 46 |
+
# 'Z' Py_ssize_t *
|
| 47 |
+
# 's' char *
|
| 48 |
+
# 'S' char **
|
| 49 |
+
# 'r' int used only to signal exception
|
| 50 |
+
# 'B' Py_buffer *
|
| 51 |
+
# '-' dummy 'self' argument (not used)
|
| 52 |
+
# '*' rest of args passed as generic Python
|
| 53 |
+
# arg tuple and kw dict (must be last
|
| 54 |
+
# char in format string)
|
| 55 |
+
# '?' optional object arg (currently for pow only)
|
| 56 |
+
|
| 57 |
+
format_map = {
|
| 58 |
+
'O': PyrexTypes.py_object_type,
|
| 59 |
+
'v': PyrexTypes.c_void_type,
|
| 60 |
+
'p': PyrexTypes.c_void_ptr_type,
|
| 61 |
+
'P': PyrexTypes.c_void_ptr_ptr_type,
|
| 62 |
+
'i': PyrexTypes.c_int_type,
|
| 63 |
+
'b': PyrexTypes.c_bint_type,
|
| 64 |
+
'I': PyrexTypes.c_int_ptr_type,
|
| 65 |
+
'l': PyrexTypes.c_long_type,
|
| 66 |
+
'f': PyrexTypes.c_float_type,
|
| 67 |
+
'd': PyrexTypes.c_double_type,
|
| 68 |
+
'h': PyrexTypes.c_py_hash_t_type,
|
| 69 |
+
'z': PyrexTypes.c_py_ssize_t_type,
|
| 70 |
+
'Z': PyrexTypes.c_py_ssize_t_ptr_type,
|
| 71 |
+
's': PyrexTypes.c_char_ptr_type,
|
| 72 |
+
'S': PyrexTypes.c_char_ptr_ptr_type,
|
| 73 |
+
'r': PyrexTypes.c_returncode_type,
|
| 74 |
+
'B': PyrexTypes.c_py_buffer_ptr_type,
|
| 75 |
+
'?': PyrexTypes.py_object_type
|
| 76 |
+
# 'T', '-' and '*' are handled otherwise
|
| 77 |
+
# and are not looked up in here
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
type_to_format_map = dict(
|
| 81 |
+
(type_, format_) for format_, type_ in format_map.items())
|
| 82 |
+
|
| 83 |
+
error_value_map = {
|
| 84 |
+
'O': "NULL",
|
| 85 |
+
'T': "NULL",
|
| 86 |
+
'i': "-1",
|
| 87 |
+
'b': "-1",
|
| 88 |
+
'l': "-1",
|
| 89 |
+
'r': "-1",
|
| 90 |
+
'h': "-1",
|
| 91 |
+
'z': "-1",
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
# Use METH_FASTCALL instead of METH_VARARGS
|
| 95 |
+
use_fastcall = False
|
| 96 |
+
|
| 97 |
+
def __init__(self, arg_format, ret_format, nogil=False):
|
| 98 |
+
self.has_dummy_arg = False
|
| 99 |
+
self.has_generic_args = False
|
| 100 |
+
self.optional_object_arg_count = 0
|
| 101 |
+
if arg_format[:1] == '-':
|
| 102 |
+
self.has_dummy_arg = True
|
| 103 |
+
arg_format = arg_format[1:]
|
| 104 |
+
if arg_format[-1:] == '*':
|
| 105 |
+
self.has_generic_args = True
|
| 106 |
+
arg_format = arg_format[:-1]
|
| 107 |
+
if arg_format[-1:] == '?':
|
| 108 |
+
self.optional_object_arg_count += 1
|
| 109 |
+
self.fixed_arg_format = arg_format
|
| 110 |
+
self.ret_format = ret_format
|
| 111 |
+
self.error_value = self.error_value_map.get(ret_format, None)
|
| 112 |
+
self.exception_check = ret_format != 'r' and self.error_value is not None
|
| 113 |
+
self.is_staticmethod = False
|
| 114 |
+
self.nogil = nogil
|
| 115 |
+
|
| 116 |
+
def __repr__(self):
|
| 117 |
+
return '<Signature[%s(%s%s)]>' % (
|
| 118 |
+
self.ret_format,
|
| 119 |
+
', '.join(self.fixed_arg_format),
|
| 120 |
+
'*' if self.has_generic_args else '')
|
| 121 |
+
|
| 122 |
+
def min_num_fixed_args(self):
|
| 123 |
+
return self.max_num_fixed_args() - self.optional_object_arg_count
|
| 124 |
+
|
| 125 |
+
def max_num_fixed_args(self):
|
| 126 |
+
return len(self.fixed_arg_format)
|
| 127 |
+
|
| 128 |
+
def is_self_arg(self, i):
|
| 129 |
+
# argument is 'self' for methods or 'class' for classmethods
|
| 130 |
+
return self.fixed_arg_format[i] == 'T'
|
| 131 |
+
|
| 132 |
+
def returns_self_type(self):
|
| 133 |
+
# return type is same as 'self' argument type
|
| 134 |
+
return self.ret_format == 'T'
|
| 135 |
+
|
| 136 |
+
def fixed_arg_type(self, i):
|
| 137 |
+
return self.format_map[self.fixed_arg_format[i]]
|
| 138 |
+
|
| 139 |
+
def return_type(self):
|
| 140 |
+
return self.format_map[self.ret_format]
|
| 141 |
+
|
| 142 |
+
def format_from_type(self, arg_type):
|
| 143 |
+
if arg_type.is_pyobject:
|
| 144 |
+
arg_type = PyrexTypes.py_object_type
|
| 145 |
+
return self.type_to_format_map[arg_type]
|
| 146 |
+
|
| 147 |
+
def exception_value(self):
|
| 148 |
+
return self.error_value_map.get(self.ret_format)
|
| 149 |
+
|
| 150 |
+
def function_type(self, self_arg_override=None):
|
| 151 |
+
# Construct a C function type descriptor for this signature
|
| 152 |
+
args = []
|
| 153 |
+
for i in range(self.max_num_fixed_args()):
|
| 154 |
+
if self_arg_override is not None and self.is_self_arg(i):
|
| 155 |
+
assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg)
|
| 156 |
+
args.append(self_arg_override)
|
| 157 |
+
else:
|
| 158 |
+
arg_type = self.fixed_arg_type(i)
|
| 159 |
+
args.append(PyrexTypes.CFuncTypeArg("", arg_type, None))
|
| 160 |
+
if self_arg_override is not None and self.returns_self_type():
|
| 161 |
+
ret_type = self_arg_override.type
|
| 162 |
+
else:
|
| 163 |
+
ret_type = self.return_type()
|
| 164 |
+
exc_value = self.exception_value()
|
| 165 |
+
return PyrexTypes.CFuncType(
|
| 166 |
+
ret_type, args, exception_value=exc_value,
|
| 167 |
+
exception_check=self.exception_check,
|
| 168 |
+
nogil=self.nogil)
|
| 169 |
+
|
| 170 |
+
def method_flags(self):
|
| 171 |
+
if self.ret_format == "O":
|
| 172 |
+
full_args = self.fixed_arg_format
|
| 173 |
+
if self.has_dummy_arg:
|
| 174 |
+
full_args = "O" + full_args
|
| 175 |
+
if full_args in ["O", "T"]:
|
| 176 |
+
if not self.has_generic_args:
|
| 177 |
+
return [method_noargs]
|
| 178 |
+
elif self.use_fastcall:
|
| 179 |
+
return [method_fastcall, method_keywords]
|
| 180 |
+
else:
|
| 181 |
+
return [method_varargs, method_keywords]
|
| 182 |
+
elif full_args in ["OO", "TO"] and not self.has_generic_args:
|
| 183 |
+
return [method_onearg]
|
| 184 |
+
|
| 185 |
+
if self.is_staticmethod:
|
| 186 |
+
if self.use_fastcall:
|
| 187 |
+
return [method_fastcall, method_keywords]
|
| 188 |
+
else:
|
| 189 |
+
return [method_varargs, method_keywords]
|
| 190 |
+
return None
|
| 191 |
+
|
| 192 |
+
def method_function_type(self):
|
| 193 |
+
# Return the C function type
|
| 194 |
+
mflags = self.method_flags()
|
| 195 |
+
kw = "WithKeywords" if (method_keywords in mflags) else ""
|
| 196 |
+
for m in mflags:
|
| 197 |
+
if m == method_noargs or m == method_onearg:
|
| 198 |
+
return "PyCFunction"
|
| 199 |
+
if m == method_varargs:
|
| 200 |
+
return "PyCFunction" + kw
|
| 201 |
+
if m == method_fastcall:
|
| 202 |
+
return "__Pyx_PyCFunction_FastCall" + kw
|
| 203 |
+
return None
|
| 204 |
+
|
| 205 |
+
def with_fastcall(self):
|
| 206 |
+
# Return a copy of this Signature with use_fastcall=True
|
| 207 |
+
sig = copy.copy(self)
|
| 208 |
+
sig.use_fastcall = True
|
| 209 |
+
return sig
|
| 210 |
+
|
| 211 |
+
@property
|
| 212 |
+
def fastvar(self):
|
| 213 |
+
# Used to select variants of functions, one dealing with METH_VARARGS
|
| 214 |
+
# and one dealing with __Pyx_METH_FASTCALL
|
| 215 |
+
if self.use_fastcall:
|
| 216 |
+
return "FASTCALL"
|
| 217 |
+
else:
|
| 218 |
+
return "VARARGS"
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
class SlotDescriptor(object):
|
| 222 |
+
# Abstract base class for type slot descriptors.
|
| 223 |
+
#
|
| 224 |
+
# slot_name string Member name of the slot in the type object
|
| 225 |
+
# is_initialised_dynamically Is initialised by code in the module init function
|
| 226 |
+
# is_inherited Is inherited by subtypes (see PyType_Ready())
|
| 227 |
+
# py3 Indicates presence of slot in Python 3
|
| 228 |
+
# py2 Indicates presence of slot in Python 2
|
| 229 |
+
# ifdef Full #ifdef string that slot is wrapped in. Using this causes py3, py2 and flags to be ignored.)
|
| 230 |
+
# used_ifdef Full #ifdef string that the slot value is wrapped in (otherwise it is assigned NULL)
|
| 231 |
+
# Unlike "ifdef" the slot is defined and this just controls if it receives a value
|
| 232 |
+
|
| 233 |
+
def __init__(self, slot_name, dynamic=False, inherited=False,
|
| 234 |
+
py3=True, py2=True, ifdef=None, is_binop=False,
|
| 235 |
+
used_ifdef=None):
|
| 236 |
+
self.slot_name = slot_name
|
| 237 |
+
self.is_initialised_dynamically = dynamic
|
| 238 |
+
self.is_inherited = inherited
|
| 239 |
+
self.ifdef = ifdef
|
| 240 |
+
self.used_ifdef = used_ifdef
|
| 241 |
+
self.py3 = py3
|
| 242 |
+
self.py2 = py2
|
| 243 |
+
self.is_binop = is_binop
|
| 244 |
+
|
| 245 |
+
def slot_code(self, scope):
|
| 246 |
+
raise NotImplementedError()
|
| 247 |
+
|
| 248 |
+
def spec_value(self, scope):
|
| 249 |
+
return self.slot_code(scope)
|
| 250 |
+
|
| 251 |
+
def preprocessor_guard_code(self):
|
| 252 |
+
ifdef = self.ifdef
|
| 253 |
+
py2 = self.py2
|
| 254 |
+
py3 = self.py3
|
| 255 |
+
guard = None
|
| 256 |
+
if ifdef:
|
| 257 |
+
guard = "#if %s" % ifdef
|
| 258 |
+
elif not py3 or py3 == '<RESERVED>':
|
| 259 |
+
guard = "#if PY_MAJOR_VERSION < 3"
|
| 260 |
+
elif not py2:
|
| 261 |
+
guard = "#if PY_MAJOR_VERSION >= 3"
|
| 262 |
+
return guard
|
| 263 |
+
|
| 264 |
+
def generate_spec(self, scope, code):
|
| 265 |
+
if self.is_initialised_dynamically:
|
| 266 |
+
return
|
| 267 |
+
value = self.spec_value(scope)
|
| 268 |
+
if value == "0":
|
| 269 |
+
return
|
| 270 |
+
preprocessor_guard = self.preprocessor_guard_code()
|
| 271 |
+
if not preprocessor_guard:
|
| 272 |
+
if self.py3 and self.slot_name.startswith('bf_'):
|
| 273 |
+
# The buffer protocol requires Limited API 3.11, so check if the spec slots are available.
|
| 274 |
+
preprocessor_guard = "#if defined(Py_%s)" % self.slot_name
|
| 275 |
+
if preprocessor_guard:
|
| 276 |
+
code.putln(preprocessor_guard)
|
| 277 |
+
code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
|
| 278 |
+
if preprocessor_guard:
|
| 279 |
+
code.putln("#endif")
|
| 280 |
+
|
| 281 |
+
def generate(self, scope, code):
|
| 282 |
+
preprocessor_guard = self.preprocessor_guard_code()
|
| 283 |
+
if preprocessor_guard:
|
| 284 |
+
code.putln(preprocessor_guard)
|
| 285 |
+
|
| 286 |
+
end_pypy_guard = False
|
| 287 |
+
if self.is_initialised_dynamically:
|
| 288 |
+
value = "0"
|
| 289 |
+
else:
|
| 290 |
+
value = self.slot_code(scope)
|
| 291 |
+
if value == "0" and self.is_inherited:
|
| 292 |
+
# PyPy currently has a broken PyType_Ready() that fails to
|
| 293 |
+
# inherit some slots. To work around this, we explicitly
|
| 294 |
+
# set inherited slots here, but only in PyPy since CPython
|
| 295 |
+
# handles this better than we do (except for buffer slots in type specs).
|
| 296 |
+
inherited_value = value
|
| 297 |
+
current_scope = scope
|
| 298 |
+
while (inherited_value == "0"
|
| 299 |
+
and current_scope.parent_type
|
| 300 |
+
and current_scope.parent_type.base_type
|
| 301 |
+
and current_scope.parent_type.base_type.scope):
|
| 302 |
+
current_scope = current_scope.parent_type.base_type.scope
|
| 303 |
+
inherited_value = self.slot_code(current_scope)
|
| 304 |
+
if inherited_value != "0":
|
| 305 |
+
# we always need inherited buffer slots for the type spec
|
| 306 |
+
is_buffer_slot = int(self.slot_name in ("bf_getbuffer", "bf_releasebuffer"))
|
| 307 |
+
code.putln("#if CYTHON_COMPILING_IN_PYPY || %d" % is_buffer_slot)
|
| 308 |
+
code.putln("%s, /*%s*/" % (inherited_value, self.slot_name))
|
| 309 |
+
code.putln("#else")
|
| 310 |
+
end_pypy_guard = True
|
| 311 |
+
|
| 312 |
+
if self.used_ifdef:
|
| 313 |
+
code.putln("#if %s" % self.used_ifdef)
|
| 314 |
+
code.putln("%s, /*%s*/" % (value, self.slot_name))
|
| 315 |
+
if self.used_ifdef:
|
| 316 |
+
code.putln("#else")
|
| 317 |
+
code.putln("NULL, /*%s*/" % self.slot_name)
|
| 318 |
+
code.putln("#endif")
|
| 319 |
+
|
| 320 |
+
if end_pypy_guard:
|
| 321 |
+
code.putln("#endif")
|
| 322 |
+
|
| 323 |
+
if self.py3 == '<RESERVED>':
|
| 324 |
+
code.putln("#else")
|
| 325 |
+
code.putln("0, /*reserved*/")
|
| 326 |
+
if preprocessor_guard:
|
| 327 |
+
code.putln("#endif")
|
| 328 |
+
|
| 329 |
+
# Some C implementations have trouble statically
|
| 330 |
+
# initialising a global with a pointer to an extern
|
| 331 |
+
# function, so we initialise some of the type slots
|
| 332 |
+
# in the module init function instead.
|
| 333 |
+
|
| 334 |
+
def generate_dynamic_init_code(self, scope, code):
|
| 335 |
+
if self.is_initialised_dynamically:
|
| 336 |
+
self.generate_set_slot_code(
|
| 337 |
+
self.slot_code(scope), scope, code)
|
| 338 |
+
|
| 339 |
+
def generate_set_slot_code(self, value, scope, code):
|
| 340 |
+
if value == "0":
|
| 341 |
+
return
|
| 342 |
+
|
| 343 |
+
if scope.parent_type.typeptr_cname:
|
| 344 |
+
target = "%s->%s" % (scope.parent_type.typeptr_cname, self.slot_name)
|
| 345 |
+
else:
|
| 346 |
+
assert scope.parent_type.typeobj_cname
|
| 347 |
+
target = "%s.%s" % (scope.parent_type.typeobj_cname, self.slot_name)
|
| 348 |
+
|
| 349 |
+
code.putln("%s = %s;" % (target, value))
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
class FixedSlot(SlotDescriptor):
|
| 353 |
+
# Descriptor for a type slot with a fixed value.
|
| 354 |
+
#
|
| 355 |
+
# value string
|
| 356 |
+
|
| 357 |
+
def __init__(self, slot_name, value, py3=True, py2=True, ifdef=None):
|
| 358 |
+
SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2, ifdef=ifdef)
|
| 359 |
+
self.value = value
|
| 360 |
+
|
| 361 |
+
def slot_code(self, scope):
|
| 362 |
+
return self.value
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
class EmptySlot(FixedSlot):
|
| 366 |
+
# Descriptor for a type slot whose value is always 0.
|
| 367 |
+
|
| 368 |
+
def __init__(self, slot_name, py3=True, py2=True, ifdef=None):
|
| 369 |
+
FixedSlot.__init__(self, slot_name, "0", py3=py3, py2=py2, ifdef=ifdef)
|
| 370 |
+
|
| 371 |
+
|
| 372 |
+
class MethodSlot(SlotDescriptor):
|
| 373 |
+
# Type slot descriptor for a user-definable method.
|
| 374 |
+
#
|
| 375 |
+
# signature Signature
|
| 376 |
+
# method_name string The __xxx__ name of the method
|
| 377 |
+
# alternatives [string] Alternative list of __xxx__ names for the method
|
| 378 |
+
|
| 379 |
+
def __init__(self, signature, slot_name, method_name, method_name_to_slot,
|
| 380 |
+
fallback=None, py3=True, py2=True, ifdef=None, inherited=True):
|
| 381 |
+
SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2,
|
| 382 |
+
ifdef=ifdef, inherited=inherited)
|
| 383 |
+
self.signature = signature
|
| 384 |
+
self.slot_name = slot_name
|
| 385 |
+
self.method_name = method_name
|
| 386 |
+
self.alternatives = []
|
| 387 |
+
method_name_to_slot[method_name] = self
|
| 388 |
+
#
|
| 389 |
+
if fallback:
|
| 390 |
+
self.alternatives.append(fallback)
|
| 391 |
+
for alt in (self.py2, self.py3):
|
| 392 |
+
if isinstance(alt, (tuple, list)):
|
| 393 |
+
slot_name, method_name = alt
|
| 394 |
+
self.alternatives.append(method_name)
|
| 395 |
+
method_name_to_slot[method_name] = self
|
| 396 |
+
|
| 397 |
+
def slot_code(self, scope):
|
| 398 |
+
entry = scope.lookup_here(self.method_name)
|
| 399 |
+
if entry and entry.is_special and entry.func_cname:
|
| 400 |
+
return entry.func_cname
|
| 401 |
+
for method_name in self.alternatives:
|
| 402 |
+
entry = scope.lookup_here(method_name)
|
| 403 |
+
if entry and entry.is_special and entry.func_cname:
|
| 404 |
+
return entry.func_cname
|
| 405 |
+
return "0"
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
class InternalMethodSlot(SlotDescriptor):
|
| 409 |
+
# Type slot descriptor for a method which is always
|
| 410 |
+
# synthesized by Cython.
|
| 411 |
+
#
|
| 412 |
+
# slot_name string Member name of the slot in the type object
|
| 413 |
+
|
| 414 |
+
def __init__(self, slot_name, **kargs):
|
| 415 |
+
SlotDescriptor.__init__(self, slot_name, **kargs)
|
| 416 |
+
|
| 417 |
+
def slot_code(self, scope):
|
| 418 |
+
return scope.mangle_internal(self.slot_name)
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
class GCDependentSlot(InternalMethodSlot):
|
| 422 |
+
# Descriptor for a slot whose value depends on whether
|
| 423 |
+
# the type participates in GC.
|
| 424 |
+
|
| 425 |
+
def __init__(self, slot_name, **kargs):
|
| 426 |
+
InternalMethodSlot.__init__(self, slot_name, **kargs)
|
| 427 |
+
|
| 428 |
+
def slot_code(self, scope):
|
| 429 |
+
if not scope.needs_gc():
|
| 430 |
+
return "0"
|
| 431 |
+
if not scope.has_cyclic_pyobject_attrs:
|
| 432 |
+
# if the type does not have GC relevant object attributes, it can
|
| 433 |
+
# delegate GC methods to its parent - iff the parent functions
|
| 434 |
+
# are defined in the same module
|
| 435 |
+
parent_type_scope = scope.parent_type.base_type.scope
|
| 436 |
+
if scope.parent_scope is parent_type_scope.parent_scope:
|
| 437 |
+
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
|
| 438 |
+
if entry.visibility != 'extern':
|
| 439 |
+
return self.slot_code(parent_type_scope)
|
| 440 |
+
return InternalMethodSlot.slot_code(self, scope)
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
class GCClearReferencesSlot(GCDependentSlot):
|
| 444 |
+
|
| 445 |
+
def slot_code(self, scope):
|
| 446 |
+
if scope.needs_tp_clear():
|
| 447 |
+
return GCDependentSlot.slot_code(self, scope)
|
| 448 |
+
return "0"
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
class ConstructorSlot(InternalMethodSlot):
|
| 452 |
+
# Descriptor for tp_new and tp_dealloc.
|
| 453 |
+
|
| 454 |
+
def __init__(self, slot_name, method=None, **kargs):
|
| 455 |
+
InternalMethodSlot.__init__(self, slot_name, **kargs)
|
| 456 |
+
self.method = method
|
| 457 |
+
|
| 458 |
+
def _needs_own(self, scope):
|
| 459 |
+
if (scope.parent_type.base_type
|
| 460 |
+
and not scope.has_pyobject_attrs
|
| 461 |
+
and not scope.has_memoryview_attrs
|
| 462 |
+
and not scope.has_cpp_constructable_attrs
|
| 463 |
+
and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)):
|
| 464 |
+
entry = scope.lookup_here(self.method) if self.method else None
|
| 465 |
+
if not (entry and entry.is_special):
|
| 466 |
+
return False
|
| 467 |
+
# Unless we can safely delegate to the parent, all types need a tp_new().
|
| 468 |
+
return True
|
| 469 |
+
|
| 470 |
+
def _parent_slot_function(self, scope):
|
| 471 |
+
parent_type_scope = scope.parent_type.base_type.scope
|
| 472 |
+
if scope.parent_scope is parent_type_scope.parent_scope:
|
| 473 |
+
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
|
| 474 |
+
if entry.visibility != 'extern':
|
| 475 |
+
return self.slot_code(parent_type_scope)
|
| 476 |
+
return None
|
| 477 |
+
|
| 478 |
+
def slot_code(self, scope):
|
| 479 |
+
if not self._needs_own(scope):
|
| 480 |
+
# if the type does not have object attributes, it can
|
| 481 |
+
# delegate GC methods to its parent - iff the parent
|
| 482 |
+
# functions are defined in the same module
|
| 483 |
+
slot_code = self._parent_slot_function(scope)
|
| 484 |
+
return slot_code or '0'
|
| 485 |
+
return InternalMethodSlot.slot_code(self, scope)
|
| 486 |
+
|
| 487 |
+
def spec_value(self, scope):
|
| 488 |
+
slot_function = self.slot_code(scope)
|
| 489 |
+
if self.slot_name == "tp_dealloc" and slot_function != scope.mangle_internal("tp_dealloc"):
|
| 490 |
+
# Not used => inherit from base type.
|
| 491 |
+
return "0"
|
| 492 |
+
return slot_function
|
| 493 |
+
|
| 494 |
+
def generate_dynamic_init_code(self, scope, code):
|
| 495 |
+
if self.slot_code(scope) != '0':
|
| 496 |
+
return
|
| 497 |
+
# If we don't have our own slot function and don't know the
|
| 498 |
+
# parent function statically, copy it dynamically.
|
| 499 |
+
base_type = scope.parent_type.base_type
|
| 500 |
+
if base_type.typeptr_cname:
|
| 501 |
+
src = '%s->%s' % (base_type.typeptr_cname, self.slot_name)
|
| 502 |
+
elif base_type.is_extension_type and base_type.typeobj_cname:
|
| 503 |
+
src = '%s.%s' % (base_type.typeobj_cname, self.slot_name)
|
| 504 |
+
else:
|
| 505 |
+
return
|
| 506 |
+
|
| 507 |
+
self.generate_set_slot_code(src, scope, code)
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
class SyntheticSlot(InternalMethodSlot):
|
| 511 |
+
# Type slot descriptor for a synthesized method which
|
| 512 |
+
# dispatches to one or more user-defined methods depending
|
| 513 |
+
# on its arguments. If none of the relevant methods are
|
| 514 |
+
# defined, the method will not be synthesized and an
|
| 515 |
+
# alternative default value will be placed in the type
|
| 516 |
+
# slot.
|
| 517 |
+
|
| 518 |
+
def __init__(self, slot_name, user_methods, default_value, **kargs):
|
| 519 |
+
InternalMethodSlot.__init__(self, slot_name, **kargs)
|
| 520 |
+
self.user_methods = user_methods
|
| 521 |
+
self.default_value = default_value
|
| 522 |
+
|
| 523 |
+
def slot_code(self, scope):
|
| 524 |
+
if scope.defines_any_special(self.user_methods):
|
| 525 |
+
return InternalMethodSlot.slot_code(self, scope)
|
| 526 |
+
else:
|
| 527 |
+
return self.default_value
|
| 528 |
+
|
| 529 |
+
def spec_value(self, scope):
|
| 530 |
+
return self.slot_code(scope)
|
| 531 |
+
|
| 532 |
+
|
| 533 |
+
class BinopSlot(SyntheticSlot):
|
| 534 |
+
def __init__(self, signature, slot_name, left_method, method_name_to_slot, **kargs):
|
| 535 |
+
assert left_method.startswith('__')
|
| 536 |
+
right_method = '__r' + left_method[2:]
|
| 537 |
+
SyntheticSlot.__init__(
|
| 538 |
+
self, slot_name, [left_method, right_method], "0", is_binop=True, **kargs)
|
| 539 |
+
# MethodSlot causes special method registration.
|
| 540 |
+
self.left_slot = MethodSlot(signature, "", left_method, method_name_to_slot, **kargs)
|
| 541 |
+
self.right_slot = MethodSlot(signature, "", right_method, method_name_to_slot, **kargs)
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
class RichcmpSlot(MethodSlot):
|
| 545 |
+
def slot_code(self, scope):
|
| 546 |
+
entry = scope.lookup_here(self.method_name)
|
| 547 |
+
if entry and entry.is_special and entry.func_cname:
|
| 548 |
+
return entry.func_cname
|
| 549 |
+
elif scope.defines_any_special(richcmp_special_methods):
|
| 550 |
+
return scope.mangle_internal(self.slot_name)
|
| 551 |
+
else:
|
| 552 |
+
return "0"
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
class TypeFlagsSlot(SlotDescriptor):
|
| 556 |
+
# Descriptor for the type flags slot.
|
| 557 |
+
|
| 558 |
+
def slot_code(self, scope):
|
| 559 |
+
value = "Py_TPFLAGS_DEFAULT"
|
| 560 |
+
if scope.directives['type_version_tag']:
|
| 561 |
+
# it's not in 'Py_TPFLAGS_DEFAULT' in Py2
|
| 562 |
+
value += "|Py_TPFLAGS_HAVE_VERSION_TAG"
|
| 563 |
+
else:
|
| 564 |
+
# it's enabled in 'Py_TPFLAGS_DEFAULT' in Py3
|
| 565 |
+
value = "(%s&~Py_TPFLAGS_HAVE_VERSION_TAG)" % value
|
| 566 |
+
value += "|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
|
| 567 |
+
if not scope.parent_type.is_final_type:
|
| 568 |
+
value += "|Py_TPFLAGS_BASETYPE"
|
| 569 |
+
if scope.needs_gc():
|
| 570 |
+
value += "|Py_TPFLAGS_HAVE_GC"
|
| 571 |
+
if scope.may_have_finalize():
|
| 572 |
+
value += "|Py_TPFLAGS_HAVE_FINALIZE"
|
| 573 |
+
if scope.parent_type.has_sequence_flag:
|
| 574 |
+
value += "|Py_TPFLAGS_SEQUENCE"
|
| 575 |
+
return value
|
| 576 |
+
|
| 577 |
+
def generate_spec(self, scope, code):
|
| 578 |
+
# Flags are stored in the PyType_Spec, not in a PyType_Slot.
|
| 579 |
+
return
|
| 580 |
+
|
| 581 |
+
|
| 582 |
+
class DocStringSlot(SlotDescriptor):
|
| 583 |
+
# Descriptor for the docstring slot.
|
| 584 |
+
|
| 585 |
+
def slot_code(self, scope):
|
| 586 |
+
doc = scope.doc
|
| 587 |
+
if doc is None:
|
| 588 |
+
return "0"
|
| 589 |
+
if doc.is_unicode:
|
| 590 |
+
doc = doc.as_utf8_string()
|
| 591 |
+
return "PyDoc_STR(%s)" % doc.as_c_string_literal()
|
| 592 |
+
|
| 593 |
+
|
| 594 |
+
class SuiteSlot(SlotDescriptor):
|
| 595 |
+
# Descriptor for a substructure of the type object.
|
| 596 |
+
#
|
| 597 |
+
# sub_slots [SlotDescriptor]
|
| 598 |
+
|
| 599 |
+
def __init__(self, sub_slots, slot_type, slot_name, substructures, ifdef=None):
|
| 600 |
+
SlotDescriptor.__init__(self, slot_name, ifdef=ifdef)
|
| 601 |
+
self.sub_slots = sub_slots
|
| 602 |
+
self.slot_type = slot_type
|
| 603 |
+
substructures.append(self)
|
| 604 |
+
|
| 605 |
+
def is_empty(self, scope):
|
| 606 |
+
for slot in self.sub_slots:
|
| 607 |
+
if slot.slot_code(scope) != "0":
|
| 608 |
+
return False
|
| 609 |
+
return True
|
| 610 |
+
|
| 611 |
+
def substructure_cname(self, scope):
|
| 612 |
+
return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
|
| 613 |
+
|
| 614 |
+
def slot_code(self, scope):
|
| 615 |
+
if not self.is_empty(scope):
|
| 616 |
+
return "&%s" % self.substructure_cname(scope)
|
| 617 |
+
return "0"
|
| 618 |
+
|
| 619 |
+
def generate_substructure(self, scope, code):
|
| 620 |
+
if not self.is_empty(scope):
|
| 621 |
+
code.putln("")
|
| 622 |
+
if self.ifdef:
|
| 623 |
+
code.putln("#if %s" % self.ifdef)
|
| 624 |
+
code.putln(
|
| 625 |
+
"static %s %s = {" % (
|
| 626 |
+
self.slot_type,
|
| 627 |
+
self.substructure_cname(scope)))
|
| 628 |
+
for slot in self.sub_slots:
|
| 629 |
+
slot.generate(scope, code)
|
| 630 |
+
code.putln("};")
|
| 631 |
+
if self.ifdef:
|
| 632 |
+
code.putln("#endif")
|
| 633 |
+
|
| 634 |
+
def generate_spec(self, scope, code):
|
| 635 |
+
for slot in self.sub_slots:
|
| 636 |
+
slot.generate_spec(scope, code)
|
| 637 |
+
|
| 638 |
+
class MethodTableSlot(SlotDescriptor):
|
| 639 |
+
# Slot descriptor for the method table.
|
| 640 |
+
|
| 641 |
+
def slot_code(self, scope):
|
| 642 |
+
if scope.pyfunc_entries:
|
| 643 |
+
return scope.method_table_cname
|
| 644 |
+
else:
|
| 645 |
+
return "0"
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
class MemberTableSlot(SlotDescriptor):
|
| 649 |
+
# Slot descriptor for the table of Python-accessible attributes.
|
| 650 |
+
|
| 651 |
+
def slot_code(self, scope):
|
| 652 |
+
# Only used in specs.
|
| 653 |
+
return "0"
|
| 654 |
+
|
| 655 |
+
def get_member_specs(self, scope):
|
| 656 |
+
return [
|
| 657 |
+
get_slot_by_name("tp_dictoffset", scope.directives).members_slot_value(scope),
|
| 658 |
+
#get_slot_by_name("tp_weaklistoffset").spec_value(scope),
|
| 659 |
+
]
|
| 660 |
+
|
| 661 |
+
def is_empty(self, scope):
|
| 662 |
+
for member_entry in self.get_member_specs(scope):
|
| 663 |
+
if member_entry:
|
| 664 |
+
return False
|
| 665 |
+
return True
|
| 666 |
+
|
| 667 |
+
def substructure_cname(self, scope):
|
| 668 |
+
return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
|
| 669 |
+
|
| 670 |
+
def generate_substructure_spec(self, scope, code):
|
| 671 |
+
if self.is_empty(scope):
|
| 672 |
+
return
|
| 673 |
+
from .Code import UtilityCode
|
| 674 |
+
code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStructmemberH", "ModuleSetupCode.c"))
|
| 675 |
+
|
| 676 |
+
code.putln("static struct PyMemberDef %s[] = {" % self.substructure_cname(scope))
|
| 677 |
+
for member_entry in self.get_member_specs(scope):
|
| 678 |
+
if member_entry:
|
| 679 |
+
code.putln(member_entry)
|
| 680 |
+
code.putln("{NULL, 0, 0, 0, NULL}")
|
| 681 |
+
code.putln("};")
|
| 682 |
+
|
| 683 |
+
def spec_value(self, scope):
|
| 684 |
+
if self.is_empty(scope):
|
| 685 |
+
return "0"
|
| 686 |
+
return self.substructure_cname(scope)
|
| 687 |
+
|
| 688 |
+
|
| 689 |
+
class GetSetSlot(SlotDescriptor):
|
| 690 |
+
# Slot descriptor for the table of attribute get & set methods.
|
| 691 |
+
|
| 692 |
+
def slot_code(self, scope):
|
| 693 |
+
if scope.property_entries:
|
| 694 |
+
return scope.getset_table_cname
|
| 695 |
+
else:
|
| 696 |
+
return "0"
|
| 697 |
+
|
| 698 |
+
|
| 699 |
+
class BaseClassSlot(SlotDescriptor):
|
| 700 |
+
# Slot descriptor for the base class slot.
|
| 701 |
+
|
| 702 |
+
def __init__(self, name):
|
| 703 |
+
SlotDescriptor.__init__(self, name, dynamic=True)
|
| 704 |
+
|
| 705 |
+
def generate_dynamic_init_code(self, scope, code):
|
| 706 |
+
base_type = scope.parent_type.base_type
|
| 707 |
+
if base_type:
|
| 708 |
+
code.putln("%s->%s = %s;" % (
|
| 709 |
+
scope.parent_type.typeptr_cname,
|
| 710 |
+
self.slot_name,
|
| 711 |
+
base_type.typeptr_cname))
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
class DictOffsetSlot(SlotDescriptor):
|
| 715 |
+
# Slot descriptor for a class' dict offset, for dynamic attributes.
|
| 716 |
+
|
| 717 |
+
def slot_code(self, scope):
|
| 718 |
+
dict_entry = scope.lookup_here("__dict__") if not scope.is_closure_class_scope else None
|
| 719 |
+
if dict_entry and dict_entry.is_variable:
|
| 720 |
+
if getattr(dict_entry.type, 'cname', None) != 'PyDict_Type':
|
| 721 |
+
error(dict_entry.pos, "__dict__ slot must be of type 'dict'")
|
| 722 |
+
return "0"
|
| 723 |
+
type = scope.parent_type
|
| 724 |
+
if type.typedef_flag:
|
| 725 |
+
objstruct = type.objstruct_cname
|
| 726 |
+
else:
|
| 727 |
+
objstruct = "struct %s" % type.objstruct_cname
|
| 728 |
+
return ("offsetof(%s, %s)" % (
|
| 729 |
+
objstruct,
|
| 730 |
+
dict_entry.cname))
|
| 731 |
+
else:
|
| 732 |
+
return "0"
|
| 733 |
+
|
| 734 |
+
def members_slot_value(self, scope):
|
| 735 |
+
dict_offset = self.slot_code(scope)
|
| 736 |
+
if dict_offset == "0":
|
| 737 |
+
return None
|
| 738 |
+
return '{"__dictoffset__", T_PYSSIZET, %s, READONLY, NULL},' % dict_offset
|
| 739 |
+
|
| 740 |
+
## The following slots are (or could be) initialised with an
|
| 741 |
+
## extern function pointer.
|
| 742 |
+
#
|
| 743 |
+
#slots_initialised_from_extern = (
|
| 744 |
+
# "tp_free",
|
| 745 |
+
#)
|
| 746 |
+
|
| 747 |
+
#------------------------------------------------------------------------------------------
|
| 748 |
+
#
|
| 749 |
+
# Utility functions for accessing slot table data structures
|
| 750 |
+
#
|
| 751 |
+
#------------------------------------------------------------------------------------------
|
| 752 |
+
|
| 753 |
+
|
| 754 |
+
def get_property_accessor_signature(name):
|
| 755 |
+
# Return signature of accessor for an extension type
|
| 756 |
+
# property, else None.
|
| 757 |
+
return property_accessor_signatures.get(name)
|
| 758 |
+
|
| 759 |
+
|
| 760 |
+
def get_base_slot_function(scope, slot):
|
| 761 |
+
# Returns the function implementing this slot in the baseclass.
|
| 762 |
+
# This is useful for enabling the compiler to optimize calls
|
| 763 |
+
# that recursively climb the class hierarchy.
|
| 764 |
+
base_type = scope.parent_type.base_type
|
| 765 |
+
if base_type and scope.parent_scope is base_type.scope.parent_scope:
|
| 766 |
+
parent_slot = slot.slot_code(base_type.scope)
|
| 767 |
+
if parent_slot != '0':
|
| 768 |
+
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
|
| 769 |
+
if entry.visibility != 'extern':
|
| 770 |
+
return parent_slot
|
| 771 |
+
return None
|
| 772 |
+
|
| 773 |
+
|
| 774 |
+
def get_slot_function(scope, slot):
|
| 775 |
+
# Returns the function implementing this slot in the baseclass.
|
| 776 |
+
# This is useful for enabling the compiler to optimize calls
|
| 777 |
+
# that recursively climb the class hierarchy.
|
| 778 |
+
slot_code = slot.slot_code(scope)
|
| 779 |
+
if slot_code != '0':
|
| 780 |
+
entry = scope.parent_scope.lookup_here(scope.parent_type.name)
|
| 781 |
+
if entry.visibility != 'extern':
|
| 782 |
+
return slot_code
|
| 783 |
+
return None
|
| 784 |
+
|
| 785 |
+
|
| 786 |
+
def get_slot_by_name(slot_name, compiler_directives):
|
| 787 |
+
# For now, only search the type struct, no referenced sub-structs.
|
| 788 |
+
for slot in get_slot_table(compiler_directives).slot_table:
|
| 789 |
+
if slot.slot_name == slot_name:
|
| 790 |
+
return slot
|
| 791 |
+
assert False, "Slot not found: %s" % slot_name
|
| 792 |
+
|
| 793 |
+
|
| 794 |
+
def get_slot_code_by_name(scope, slot_name):
|
| 795 |
+
slot = get_slot_by_name(slot_name, scope.directives)
|
| 796 |
+
return slot.slot_code(scope)
|
| 797 |
+
|
| 798 |
+
def is_reverse_number_slot(name):
|
| 799 |
+
"""
|
| 800 |
+
Tries to identify __radd__ and friends (so the METH_COEXIST flag can be applied).
|
| 801 |
+
|
| 802 |
+
There's no great consequence if it inadvertently identifies a few other methods
|
| 803 |
+
so just use a simple rule rather than an exact list.
|
| 804 |
+
"""
|
| 805 |
+
if name.startswith("__r") and name.endswith("__"):
|
| 806 |
+
forward_name = name.replace("r", "", 1)
|
| 807 |
+
for meth in get_slot_table(None).PyNumberMethods:
|
| 808 |
+
if hasattr(meth, "right_slot"):
|
| 809 |
+
return True
|
| 810 |
+
return False
|
| 811 |
+
|
| 812 |
+
|
| 813 |
+
#------------------------------------------------------------------------------------------
|
| 814 |
+
#
|
| 815 |
+
# Signatures for generic Python functions and methods.
|
| 816 |
+
#
|
| 817 |
+
#------------------------------------------------------------------------------------------
|
| 818 |
+
|
| 819 |
+
pyfunction_signature = Signature("-*", "O")
|
| 820 |
+
pymethod_signature = Signature("T*", "O")
|
| 821 |
+
|
| 822 |
+
#------------------------------------------------------------------------------------------
|
| 823 |
+
#
|
| 824 |
+
# Signatures for simple Python functions.
|
| 825 |
+
#
|
| 826 |
+
#------------------------------------------------------------------------------------------
|
| 827 |
+
|
| 828 |
+
pyfunction_noargs = Signature("-", "O")
|
| 829 |
+
pyfunction_onearg = Signature("-O", "O")
|
| 830 |
+
|
| 831 |
+
#------------------------------------------------------------------------------------------
|
| 832 |
+
#
|
| 833 |
+
# Signatures for the various kinds of function that
|
| 834 |
+
# can appear in the type object and its substructures.
|
| 835 |
+
#
|
| 836 |
+
#------------------------------------------------------------------------------------------
|
| 837 |
+
|
| 838 |
+
unaryfunc = Signature("T", "O") # typedef PyObject * (*unaryfunc)(PyObject *);
|
| 839 |
+
binaryfunc = Signature("OO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
|
| 840 |
+
ibinaryfunc = Signature("TO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
|
| 841 |
+
powternaryfunc = Signature("OO?", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
|
| 842 |
+
ipowternaryfunc = Signature("TO?", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
|
| 843 |
+
callfunc = Signature("T*", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
|
| 844 |
+
inquiry = Signature("T", "i") # typedef int (*inquiry)(PyObject *);
|
| 845 |
+
lenfunc = Signature("T", "z") # typedef Py_ssize_t (*lenfunc)(PyObject *);
|
| 846 |
+
|
| 847 |
+
# typedef int (*coercion)(PyObject **, PyObject **);
|
| 848 |
+
intargfunc = Signature("Ti", "O") # typedef PyObject *(*intargfunc)(PyObject *, int);
|
| 849 |
+
ssizeargfunc = Signature("Tz", "O") # typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
|
| 850 |
+
intintargfunc = Signature("Tii", "O") # typedef PyObject *(*intintargfunc)(PyObject *, int, int);
|
| 851 |
+
ssizessizeargfunc = Signature("Tzz", "O") # typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t);
|
| 852 |
+
intobjargproc = Signature("TiO", 'r') # typedef int(*intobjargproc)(PyObject *, int, PyObject *);
|
| 853 |
+
ssizeobjargproc = Signature("TzO", 'r') # typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *);
|
| 854 |
+
intintobjargproc = Signature("TiiO", 'r') # typedef int(*intintobjargproc)(PyObject *, int, int, PyObject *);
|
| 855 |
+
ssizessizeobjargproc = Signature("TzzO", 'r') # typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
|
| 856 |
+
|
| 857 |
+
intintargproc = Signature("Tii", 'r')
|
| 858 |
+
ssizessizeargproc = Signature("Tzz", 'r')
|
| 859 |
+
objargfunc = Signature("TO", "O")
|
| 860 |
+
objobjargproc = Signature("TOO", 'r') # typedef int (*objobjargproc)(PyObject *, PyObject *, PyObject *);
|
| 861 |
+
readbufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*readbufferproc)(PyObject *, Py_ssize_t, void **);
|
| 862 |
+
writebufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **);
|
| 863 |
+
segcountproc = Signature("TZ", "z") # typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *);
|
| 864 |
+
charbufferproc = Signature("TzS", "z") # typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **);
|
| 865 |
+
objargproc = Signature("TO", 'r') # typedef int (*objobjproc)(PyObject *, PyObject *);
|
| 866 |
+
# typedef int (*visitproc)(PyObject *, void *);
|
| 867 |
+
# typedef int (*traverseproc)(PyObject *, visitproc, void *);
|
| 868 |
+
|
| 869 |
+
destructor = Signature("T", "v") # typedef void (*destructor)(PyObject *);
|
| 870 |
+
# printfunc = Signature("TFi", 'r') # typedef int (*printfunc)(PyObject *, FILE *, int);
|
| 871 |
+
# typedef PyObject *(*getattrfunc)(PyObject *, char *);
|
| 872 |
+
getattrofunc = Signature("TO", "O") # typedef PyObject *(*getattrofunc)(PyObject *, PyObject *);
|
| 873 |
+
# typedef int (*setattrfunc)(PyObject *, char *, PyObject *);
|
| 874 |
+
setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *);
|
| 875 |
+
delattrofunc = Signature("TO", 'r')
|
| 876 |
+
cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *);
|
| 877 |
+
reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *);
|
| 878 |
+
hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *);
|
| 879 |
+
richcmpfunc = Signature("TOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
|
| 880 |
+
getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *);
|
| 881 |
+
iternextfunc = Signature("T", "O") # typedef PyObject *(*iternextfunc) (PyObject *);
|
| 882 |
+
descrgetfunc = Signature("TOO", "O") # typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *);
|
| 883 |
+
descrsetfunc = Signature("TOO", 'r') # typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *);
|
| 884 |
+
descrdelfunc = Signature("TO", 'r')
|
| 885 |
+
initproc = Signature("T*", 'r') # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
|
| 886 |
+
# typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
|
| 887 |
+
# typedef PyObject *(*allocfunc)(struct _typeobject *, int);
|
| 888 |
+
|
| 889 |
+
getbufferproc = Signature("TBi", "r") # typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
|
| 890 |
+
releasebufferproc = Signature("TB", "v") # typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
|
| 891 |
+
|
| 892 |
+
|
| 893 |
+
#------------------------------------------------------------------------------------------
|
| 894 |
+
#
|
| 895 |
+
# Signatures for accessor methods of properties.
|
| 896 |
+
#
|
| 897 |
+
#------------------------------------------------------------------------------------------
|
| 898 |
+
|
| 899 |
+
property_accessor_signatures = {
|
| 900 |
+
'__get__': Signature("T", "O"),
|
| 901 |
+
'__set__': Signature("TO", 'r'),
|
| 902 |
+
'__del__': Signature("T", 'r')
|
| 903 |
+
}
|
| 904 |
+
|
| 905 |
+
|
| 906 |
+
PyNumberMethods_Py2only_GUARD = "PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000)"
|
| 907 |
+
|
| 908 |
+
#------------------------------------------------------------------------------------------
|
| 909 |
+
#
|
| 910 |
+
# The main slot table. This table contains descriptors for all the
|
| 911 |
+
# top-level type slots, beginning with tp_dealloc, in the order they
|
| 912 |
+
# appear in the type object.
|
| 913 |
+
#
|
| 914 |
+
# It depends on some compiler directives (currently c_api_binop_methods), so the
|
| 915 |
+
# slot tables for each set of compiler directives are generated lazily and put in
|
| 916 |
+
# the _slot_table_dict
|
| 917 |
+
#
|
| 918 |
+
#------------------------------------------------------------------------------------------
|
| 919 |
+
|
| 920 |
+
class SlotTable(object):
|
| 921 |
+
def __init__(self, old_binops):
|
| 922 |
+
# The following dictionary maps __xxx__ method names to slot descriptors.
|
| 923 |
+
method_name_to_slot = {}
|
| 924 |
+
self._get_slot_by_method_name = method_name_to_slot.get
|
| 925 |
+
self.substructures = [] # List of all SuiteSlot instances
|
| 926 |
+
|
| 927 |
+
bf = binaryfunc if old_binops else ibinaryfunc
|
| 928 |
+
ptf = powternaryfunc if old_binops else ipowternaryfunc
|
| 929 |
+
|
| 930 |
+
# Descriptor tables for the slots of the various type object
|
| 931 |
+
# substructures, in the order they appear in the structure.
|
| 932 |
+
self.PyNumberMethods = (
|
| 933 |
+
BinopSlot(bf, "nb_add", "__add__", method_name_to_slot),
|
| 934 |
+
BinopSlot(bf, "nb_subtract", "__sub__", method_name_to_slot),
|
| 935 |
+
BinopSlot(bf, "nb_multiply", "__mul__", method_name_to_slot),
|
| 936 |
+
BinopSlot(bf, "nb_divide", "__div__", method_name_to_slot,
|
| 937 |
+
ifdef = PyNumberMethods_Py2only_GUARD),
|
| 938 |
+
BinopSlot(bf, "nb_remainder", "__mod__", method_name_to_slot),
|
| 939 |
+
BinopSlot(bf, "nb_divmod", "__divmod__", method_name_to_slot),
|
| 940 |
+
BinopSlot(ptf, "nb_power", "__pow__", method_name_to_slot),
|
| 941 |
+
MethodSlot(unaryfunc, "nb_negative", "__neg__", method_name_to_slot),
|
| 942 |
+
MethodSlot(unaryfunc, "nb_positive", "__pos__", method_name_to_slot),
|
| 943 |
+
MethodSlot(unaryfunc, "nb_absolute", "__abs__", method_name_to_slot),
|
| 944 |
+
MethodSlot(inquiry, "nb_bool", "__bool__", method_name_to_slot,
|
| 945 |
+
py2 = ("nb_nonzero", "__nonzero__")),
|
| 946 |
+
MethodSlot(unaryfunc, "nb_invert", "__invert__", method_name_to_slot),
|
| 947 |
+
BinopSlot(bf, "nb_lshift", "__lshift__", method_name_to_slot),
|
| 948 |
+
BinopSlot(bf, "nb_rshift", "__rshift__", method_name_to_slot),
|
| 949 |
+
BinopSlot(bf, "nb_and", "__and__", method_name_to_slot),
|
| 950 |
+
BinopSlot(bf, "nb_xor", "__xor__", method_name_to_slot),
|
| 951 |
+
BinopSlot(bf, "nb_or", "__or__", method_name_to_slot),
|
| 952 |
+
EmptySlot("nb_coerce", ifdef = PyNumberMethods_Py2only_GUARD),
|
| 953 |
+
MethodSlot(unaryfunc, "nb_int", "__int__", method_name_to_slot, fallback="__long__"),
|
| 954 |
+
MethodSlot(unaryfunc, "nb_long", "__long__", method_name_to_slot,
|
| 955 |
+
fallback="__int__", py3 = "<RESERVED>"),
|
| 956 |
+
MethodSlot(unaryfunc, "nb_float", "__float__", method_name_to_slot),
|
| 957 |
+
MethodSlot(unaryfunc, "nb_oct", "__oct__", method_name_to_slot,
|
| 958 |
+
ifdef = PyNumberMethods_Py2only_GUARD),
|
| 959 |
+
MethodSlot(unaryfunc, "nb_hex", "__hex__", method_name_to_slot,
|
| 960 |
+
ifdef = PyNumberMethods_Py2only_GUARD),
|
| 961 |
+
|
| 962 |
+
# Added in release 2.0
|
| 963 |
+
MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__", method_name_to_slot),
|
| 964 |
+
MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__", method_name_to_slot),
|
| 965 |
+
MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__", method_name_to_slot),
|
| 966 |
+
MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", method_name_to_slot,
|
| 967 |
+
ifdef = PyNumberMethods_Py2only_GUARD),
|
| 968 |
+
MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__", method_name_to_slot),
|
| 969 |
+
MethodSlot(ptf, "nb_inplace_power", "__ipow__", method_name_to_slot),
|
| 970 |
+
MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__", method_name_to_slot),
|
| 971 |
+
MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__", method_name_to_slot),
|
| 972 |
+
MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__", method_name_to_slot),
|
| 973 |
+
MethodSlot(ibinaryfunc, "nb_inplace_xor", "__ixor__", method_name_to_slot),
|
| 974 |
+
MethodSlot(ibinaryfunc, "nb_inplace_or", "__ior__", method_name_to_slot),
|
| 975 |
+
|
| 976 |
+
# Added in release 2.2
|
| 977 |
+
# The following require the Py_TPFLAGS_HAVE_CLASS flag
|
| 978 |
+
BinopSlot(bf, "nb_floor_divide", "__floordiv__", method_name_to_slot),
|
| 979 |
+
BinopSlot(bf, "nb_true_divide", "__truediv__", method_name_to_slot),
|
| 980 |
+
MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__", method_name_to_slot),
|
| 981 |
+
MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__", method_name_to_slot),
|
| 982 |
+
|
| 983 |
+
# Added in release 2.5
|
| 984 |
+
MethodSlot(unaryfunc, "nb_index", "__index__", method_name_to_slot),
|
| 985 |
+
|
| 986 |
+
# Added in release 3.5
|
| 987 |
+
BinopSlot(bf, "nb_matrix_multiply", "__matmul__", method_name_to_slot,
|
| 988 |
+
ifdef="PY_VERSION_HEX >= 0x03050000"),
|
| 989 |
+
MethodSlot(ibinaryfunc, "nb_inplace_matrix_multiply", "__imatmul__", method_name_to_slot,
|
| 990 |
+
ifdef="PY_VERSION_HEX >= 0x03050000"),
|
| 991 |
+
)
|
| 992 |
+
|
| 993 |
+
self.PySequenceMethods = (
|
| 994 |
+
MethodSlot(lenfunc, "sq_length", "__len__", method_name_to_slot),
|
| 995 |
+
EmptySlot("sq_concat"), # nb_add used instead
|
| 996 |
+
EmptySlot("sq_repeat"), # nb_multiply used instead
|
| 997 |
+
SyntheticSlot("sq_item", ["__getitem__"], "0"), #EmptySlot("sq_item"), # mp_subscript used instead
|
| 998 |
+
MethodSlot(ssizessizeargfunc, "sq_slice", "__getslice__", method_name_to_slot),
|
| 999 |
+
EmptySlot("sq_ass_item"), # mp_ass_subscript used instead
|
| 1000 |
+
SyntheticSlot("sq_ass_slice", ["__setslice__", "__delslice__"], "0"),
|
| 1001 |
+
MethodSlot(cmpfunc, "sq_contains", "__contains__", method_name_to_slot),
|
| 1002 |
+
EmptySlot("sq_inplace_concat"), # nb_inplace_add used instead
|
| 1003 |
+
EmptySlot("sq_inplace_repeat"), # nb_inplace_multiply used instead
|
| 1004 |
+
)
|
| 1005 |
+
|
| 1006 |
+
self.PyMappingMethods = (
|
| 1007 |
+
MethodSlot(lenfunc, "mp_length", "__len__", method_name_to_slot),
|
| 1008 |
+
MethodSlot(objargfunc, "mp_subscript", "__getitem__", method_name_to_slot),
|
| 1009 |
+
SyntheticSlot("mp_ass_subscript", ["__setitem__", "__delitem__"], "0"),
|
| 1010 |
+
)
|
| 1011 |
+
|
| 1012 |
+
self.PyBufferProcs = (
|
| 1013 |
+
MethodSlot(readbufferproc, "bf_getreadbuffer", "__getreadbuffer__", method_name_to_slot,
|
| 1014 |
+
py3 = False),
|
| 1015 |
+
MethodSlot(writebufferproc, "bf_getwritebuffer", "__getwritebuffer__", method_name_to_slot,
|
| 1016 |
+
py3 = False),
|
| 1017 |
+
MethodSlot(segcountproc, "bf_getsegcount", "__getsegcount__", method_name_to_slot,
|
| 1018 |
+
py3 = False),
|
| 1019 |
+
MethodSlot(charbufferproc, "bf_getcharbuffer", "__getcharbuffer__", method_name_to_slot,
|
| 1020 |
+
py3 = False),
|
| 1021 |
+
|
| 1022 |
+
MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", method_name_to_slot),
|
| 1023 |
+
MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", method_name_to_slot)
|
| 1024 |
+
)
|
| 1025 |
+
|
| 1026 |
+
self.PyAsyncMethods = (
|
| 1027 |
+
MethodSlot(unaryfunc, "am_await", "__await__", method_name_to_slot),
|
| 1028 |
+
MethodSlot(unaryfunc, "am_aiter", "__aiter__", method_name_to_slot),
|
| 1029 |
+
MethodSlot(unaryfunc, "am_anext", "__anext__", method_name_to_slot),
|
| 1030 |
+
EmptySlot("am_send", ifdef="PY_VERSION_HEX >= 0x030A00A3"),
|
| 1031 |
+
)
|
| 1032 |
+
|
| 1033 |
+
self.slot_table = (
|
| 1034 |
+
ConstructorSlot("tp_dealloc", '__dealloc__'),
|
| 1035 |
+
EmptySlot("tp_print", ifdef="PY_VERSION_HEX < 0x030800b4"),
|
| 1036 |
+
EmptySlot("tp_vectorcall_offset", ifdef="PY_VERSION_HEX >= 0x030800b4"),
|
| 1037 |
+
EmptySlot("tp_getattr"),
|
| 1038 |
+
EmptySlot("tp_setattr"),
|
| 1039 |
+
|
| 1040 |
+
# tp_compare (Py2) / tp_reserved (Py3<3.5) / tp_as_async (Py3.5+) is always used as tp_as_async in Py3
|
| 1041 |
+
MethodSlot(cmpfunc, "tp_compare", "__cmp__", method_name_to_slot, ifdef="PY_MAJOR_VERSION < 3"),
|
| 1042 |
+
SuiteSlot(self. PyAsyncMethods, "__Pyx_PyAsyncMethodsStruct", "tp_as_async",
|
| 1043 |
+
self.substructures, ifdef="PY_MAJOR_VERSION >= 3"),
|
| 1044 |
+
|
| 1045 |
+
MethodSlot(reprfunc, "tp_repr", "__repr__", method_name_to_slot),
|
| 1046 |
+
|
| 1047 |
+
SuiteSlot(self.PyNumberMethods, "PyNumberMethods", "tp_as_number", self.substructures),
|
| 1048 |
+
SuiteSlot(self.PySequenceMethods, "PySequenceMethods", "tp_as_sequence", self.substructures),
|
| 1049 |
+
SuiteSlot(self.PyMappingMethods, "PyMappingMethods", "tp_as_mapping", self.substructures),
|
| 1050 |
+
|
| 1051 |
+
MethodSlot(hashfunc, "tp_hash", "__hash__", method_name_to_slot,
|
| 1052 |
+
inherited=False), # Py3 checks for __richcmp__
|
| 1053 |
+
MethodSlot(callfunc, "tp_call", "__call__", method_name_to_slot),
|
| 1054 |
+
MethodSlot(reprfunc, "tp_str", "__str__", method_name_to_slot),
|
| 1055 |
+
|
| 1056 |
+
SyntheticSlot("tp_getattro", ["__getattr__","__getattribute__"], "0"), #"PyObject_GenericGetAttr"),
|
| 1057 |
+
SyntheticSlot("tp_setattro", ["__setattr__", "__delattr__"], "0"), #"PyObject_GenericSetAttr"),
|
| 1058 |
+
|
| 1059 |
+
SuiteSlot(self.PyBufferProcs, "PyBufferProcs", "tp_as_buffer", self.substructures),
|
| 1060 |
+
|
| 1061 |
+
TypeFlagsSlot("tp_flags"),
|
| 1062 |
+
DocStringSlot("tp_doc"),
|
| 1063 |
+
|
| 1064 |
+
GCDependentSlot("tp_traverse"),
|
| 1065 |
+
GCClearReferencesSlot("tp_clear"),
|
| 1066 |
+
|
| 1067 |
+
RichcmpSlot(richcmpfunc, "tp_richcompare", "__richcmp__", method_name_to_slot,
|
| 1068 |
+
inherited=False), # Py3 checks for __hash__
|
| 1069 |
+
|
| 1070 |
+
EmptySlot("tp_weaklistoffset"),
|
| 1071 |
+
|
| 1072 |
+
MethodSlot(getiterfunc, "tp_iter", "__iter__", method_name_to_slot),
|
| 1073 |
+
MethodSlot(iternextfunc, "tp_iternext", "__next__", method_name_to_slot),
|
| 1074 |
+
|
| 1075 |
+
MethodTableSlot("tp_methods"),
|
| 1076 |
+
MemberTableSlot("tp_members"),
|
| 1077 |
+
GetSetSlot("tp_getset"),
|
| 1078 |
+
|
| 1079 |
+
BaseClassSlot("tp_base"), #EmptySlot("tp_base"),
|
| 1080 |
+
EmptySlot("tp_dict"),
|
| 1081 |
+
|
| 1082 |
+
SyntheticSlot("tp_descr_get", ["__get__"], "0"),
|
| 1083 |
+
SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"),
|
| 1084 |
+
|
| 1085 |
+
DictOffsetSlot("tp_dictoffset", ifdef="!CYTHON_USE_TYPE_SPECS"), # otherwise set via "__dictoffset__" member
|
| 1086 |
+
|
| 1087 |
+
MethodSlot(initproc, "tp_init", "__init__", method_name_to_slot),
|
| 1088 |
+
EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
|
| 1089 |
+
ConstructorSlot("tp_new", "__cinit__"),
|
| 1090 |
+
EmptySlot("tp_free"),
|
| 1091 |
+
|
| 1092 |
+
EmptySlot("tp_is_gc"),
|
| 1093 |
+
EmptySlot("tp_bases"),
|
| 1094 |
+
EmptySlot("tp_mro"),
|
| 1095 |
+
EmptySlot("tp_cache"),
|
| 1096 |
+
EmptySlot("tp_subclasses"),
|
| 1097 |
+
EmptySlot("tp_weaklist"),
|
| 1098 |
+
EmptySlot("tp_del"),
|
| 1099 |
+
EmptySlot("tp_version_tag"),
|
| 1100 |
+
SyntheticSlot("tp_finalize", ["__del__"], "0", ifdef="PY_VERSION_HEX >= 0x030400a1",
|
| 1101 |
+
used_ifdef="CYTHON_USE_TP_FINALIZE"),
|
| 1102 |
+
EmptySlot("tp_vectorcall", ifdef="PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)"),
|
| 1103 |
+
EmptySlot("tp_print", ifdef="__PYX_NEED_TP_PRINT_SLOT == 1"),
|
| 1104 |
+
EmptySlot("tp_watched", ifdef="PY_VERSION_HEX >= 0x030C0000"),
|
| 1105 |
+
EmptySlot("tp_versions_used", ifdef="PY_VERSION_HEX >= 0x030d00A4"),
|
| 1106 |
+
# PyPy specific extension - only here to avoid C compiler warnings.
|
| 1107 |
+
EmptySlot("tp_pypy_flags", ifdef="CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000"),
|
| 1108 |
+
)
|
| 1109 |
+
|
| 1110 |
+
#------------------------------------------------------------------------------------------
|
| 1111 |
+
#
|
| 1112 |
+
# Descriptors for special methods which don't appear directly
|
| 1113 |
+
# in the type object or its substructures. These methods are
|
| 1114 |
+
# called from slot functions synthesized by Cython.
|
| 1115 |
+
#
|
| 1116 |
+
#------------------------------------------------------------------------------------------
|
| 1117 |
+
|
| 1118 |
+
MethodSlot(initproc, "", "__cinit__", method_name_to_slot)
|
| 1119 |
+
MethodSlot(destructor, "", "__dealloc__", method_name_to_slot)
|
| 1120 |
+
MethodSlot(destructor, "", "__del__", method_name_to_slot)
|
| 1121 |
+
MethodSlot(objobjargproc, "", "__setitem__", method_name_to_slot)
|
| 1122 |
+
MethodSlot(objargproc, "", "__delitem__", method_name_to_slot)
|
| 1123 |
+
MethodSlot(ssizessizeobjargproc, "", "__setslice__", method_name_to_slot)
|
| 1124 |
+
MethodSlot(ssizessizeargproc, "", "__delslice__", method_name_to_slot)
|
| 1125 |
+
MethodSlot(getattrofunc, "", "__getattr__", method_name_to_slot)
|
| 1126 |
+
MethodSlot(getattrofunc, "", "__getattribute__", method_name_to_slot)
|
| 1127 |
+
MethodSlot(setattrofunc, "", "__setattr__", method_name_to_slot)
|
| 1128 |
+
MethodSlot(delattrofunc, "", "__delattr__", method_name_to_slot)
|
| 1129 |
+
MethodSlot(descrgetfunc, "", "__get__", method_name_to_slot)
|
| 1130 |
+
MethodSlot(descrsetfunc, "", "__set__", method_name_to_slot)
|
| 1131 |
+
MethodSlot(descrdelfunc, "", "__delete__", method_name_to_slot)
|
| 1132 |
+
|
| 1133 |
+
def get_special_method_signature(self, name):
|
| 1134 |
+
# Given a method name, if it is a special method,
|
| 1135 |
+
# return its signature, else return None.
|
| 1136 |
+
slot = self._get_slot_by_method_name(name)
|
| 1137 |
+
if slot:
|
| 1138 |
+
return slot.signature
|
| 1139 |
+
elif name in richcmp_special_methods:
|
| 1140 |
+
return ibinaryfunc
|
| 1141 |
+
else:
|
| 1142 |
+
return None
|
| 1143 |
+
|
| 1144 |
+
def get_slot_by_method_name(self, method_name):
|
| 1145 |
+
# For now, only search the type struct, no referenced sub-structs.
|
| 1146 |
+
return self._get_slot_by_method_name(method_name)
|
| 1147 |
+
|
| 1148 |
+
def __iter__(self):
|
| 1149 |
+
# make it easier to iterate over all the slots
|
| 1150 |
+
return iter(self.slot_table)
|
| 1151 |
+
|
| 1152 |
+
|
| 1153 |
+
_slot_table_dict = {}
|
| 1154 |
+
|
| 1155 |
+
def get_slot_table(compiler_directives):
|
| 1156 |
+
if not compiler_directives:
|
| 1157 |
+
# fetch default directives here since the builtin type classes don't have
|
| 1158 |
+
# directives set
|
| 1159 |
+
from .Options import get_directive_defaults
|
| 1160 |
+
compiler_directives = get_directive_defaults()
|
| 1161 |
+
|
| 1162 |
+
old_binops = compiler_directives['c_api_binop_methods']
|
| 1163 |
+
key = (old_binops,)
|
| 1164 |
+
if key not in _slot_table_dict:
|
| 1165 |
+
_slot_table_dict[key] = SlotTable(old_binops=old_binops)
|
| 1166 |
+
return _slot_table_dict[key]
|
| 1167 |
+
|
| 1168 |
+
|
| 1169 |
+
# Populate "special_method_names" based on the default directives (so it can always be accessed quickly).
|
| 1170 |
+
special_method_names = set(get_slot_table(compiler_directives=None))
|
| 1171 |
+
|
| 1172 |
+
|
| 1173 |
+
# Method flags for python-exposed methods.
|
| 1174 |
+
|
| 1175 |
+
method_noargs = "METH_NOARGS"
|
| 1176 |
+
method_onearg = "METH_O"
|
| 1177 |
+
method_varargs = "METH_VARARGS"
|
| 1178 |
+
method_fastcall = "__Pyx_METH_FASTCALL" # Actually VARARGS on versions < 3.7
|
| 1179 |
+
method_keywords = "METH_KEYWORDS"
|
| 1180 |
+
method_coexist = "METH_COEXIST"
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/UFuncs.py
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from . import (
|
| 2 |
+
Nodes,
|
| 3 |
+
ExprNodes,
|
| 4 |
+
FusedNode,
|
| 5 |
+
TreeFragment,
|
| 6 |
+
Pipeline,
|
| 7 |
+
ParseTreeTransforms,
|
| 8 |
+
Naming,
|
| 9 |
+
UtilNodes,
|
| 10 |
+
)
|
| 11 |
+
from .Errors import error
|
| 12 |
+
from . import PyrexTypes
|
| 13 |
+
from .UtilityCode import CythonUtilityCode
|
| 14 |
+
from .Code import TempitaUtilityCode, UtilityCode
|
| 15 |
+
from .Visitor import PrintTree, TreeVisitor, VisitorTransform
|
| 16 |
+
|
| 17 |
+
numpy_int_types = [
|
| 18 |
+
"NPY_BYTE",
|
| 19 |
+
"NPY_INT8",
|
| 20 |
+
"NPY_SHORT",
|
| 21 |
+
"NPY_INT16",
|
| 22 |
+
"NPY_INT",
|
| 23 |
+
"NPY_INT32",
|
| 24 |
+
"NPY_LONG",
|
| 25 |
+
"NPY_LONGLONG",
|
| 26 |
+
"NPY_INT64",
|
| 27 |
+
]
|
| 28 |
+
numpy_uint_types = [tp.replace("NPY_", "NPY_U") for tp in numpy_int_types]
|
| 29 |
+
# note: half float type is deliberately omitted
|
| 30 |
+
numpy_numeric_types = (
|
| 31 |
+
numpy_int_types
|
| 32 |
+
+ numpy_uint_types
|
| 33 |
+
+ [
|
| 34 |
+
"NPY_FLOAT",
|
| 35 |
+
"NPY_FLOAT32",
|
| 36 |
+
"NPY_DOUBLE",
|
| 37 |
+
"NPY_FLOAT64",
|
| 38 |
+
"NPY_LONGDOUBLE",
|
| 39 |
+
]
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def _get_type_constant(pos, type_):
|
| 44 |
+
if type_.is_complex:
|
| 45 |
+
# 'is' checks don't seem to work for complex types
|
| 46 |
+
if type_ == PyrexTypes.c_float_complex_type:
|
| 47 |
+
return "NPY_CFLOAT"
|
| 48 |
+
elif type_ == PyrexTypes.c_double_complex_type:
|
| 49 |
+
return "NPY_CDOUBLE"
|
| 50 |
+
elif type_ == PyrexTypes.c_longdouble_complex_type:
|
| 51 |
+
return "NPY_CLONGDOUBLE"
|
| 52 |
+
elif type_.is_numeric:
|
| 53 |
+
postfix = type_.empty_declaration_code().upper().replace(" ", "")
|
| 54 |
+
typename = "NPY_%s" % postfix
|
| 55 |
+
if typename in numpy_numeric_types:
|
| 56 |
+
return typename
|
| 57 |
+
elif type_.is_pyobject:
|
| 58 |
+
return "NPY_OBJECT"
|
| 59 |
+
# TODO possible NPY_BOOL to bint but it needs a cast?
|
| 60 |
+
# TODO NPY_DATETIME, NPY_TIMEDELTA, NPY_STRING, NPY_UNICODE and maybe NPY_VOID might be handleable
|
| 61 |
+
error(pos, "Type '%s' cannot be used as a ufunc argument" % type_)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
class _FindCFuncDefNode(TreeVisitor):
|
| 65 |
+
"""
|
| 66 |
+
Finds the CFuncDefNode in the tree
|
| 67 |
+
|
| 68 |
+
The assumption is that there's only one CFuncDefNode
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
found_node = None
|
| 72 |
+
|
| 73 |
+
def visit_Node(self, node):
|
| 74 |
+
if self.found_node:
|
| 75 |
+
return
|
| 76 |
+
else:
|
| 77 |
+
self.visitchildren(node)
|
| 78 |
+
|
| 79 |
+
def visit_CFuncDefNode(self, node):
|
| 80 |
+
self.found_node = node
|
| 81 |
+
|
| 82 |
+
def __call__(self, tree):
|
| 83 |
+
self.visit(tree)
|
| 84 |
+
return self.found_node
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def get_cfunc_from_tree(tree):
|
| 88 |
+
return _FindCFuncDefNode()(tree)
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
class _ArgumentInfo(object):
|
| 92 |
+
"""
|
| 93 |
+
Everything related to defining an input/output argument for a ufunc
|
| 94 |
+
|
| 95 |
+
type - PyrexType
|
| 96 |
+
type_constant - str such as "NPY_INT8" representing numpy dtype constants
|
| 97 |
+
"""
|
| 98 |
+
|
| 99 |
+
def __init__(self, type, type_constant):
|
| 100 |
+
self.type = type
|
| 101 |
+
self.type_constant = type_constant
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
class UFuncConversion(object):
|
| 105 |
+
def __init__(self, node):
|
| 106 |
+
self.node = node
|
| 107 |
+
self.global_scope = node.local_scope.global_scope()
|
| 108 |
+
|
| 109 |
+
self.in_definitions = self.get_in_type_info()
|
| 110 |
+
self.out_definitions = self.get_out_type_info()
|
| 111 |
+
|
| 112 |
+
def get_in_type_info(self):
|
| 113 |
+
definitions = []
|
| 114 |
+
for n, arg in enumerate(self.node.args):
|
| 115 |
+
type_const = _get_type_constant(self.node.pos, arg.type)
|
| 116 |
+
definitions.append(_ArgumentInfo(arg.type, type_const))
|
| 117 |
+
return definitions
|
| 118 |
+
|
| 119 |
+
def get_out_type_info(self):
|
| 120 |
+
if self.node.return_type.is_ctuple:
|
| 121 |
+
components = self.node.return_type.components
|
| 122 |
+
else:
|
| 123 |
+
components = [self.node.return_type]
|
| 124 |
+
definitions = []
|
| 125 |
+
for n, type in enumerate(components):
|
| 126 |
+
definitions.append(
|
| 127 |
+
_ArgumentInfo(type, _get_type_constant(self.node.pos, type))
|
| 128 |
+
)
|
| 129 |
+
return definitions
|
| 130 |
+
|
| 131 |
+
def generate_cy_utility_code(self):
|
| 132 |
+
arg_types = [a.type for a in self.in_definitions]
|
| 133 |
+
out_types = [a.type for a in self.out_definitions]
|
| 134 |
+
inline_func_decl = self.node.entry.type.declaration_code(
|
| 135 |
+
self.node.entry.cname, pyrex=True
|
| 136 |
+
)
|
| 137 |
+
self.node.entry.used = True
|
| 138 |
+
|
| 139 |
+
ufunc_cname = self.global_scope.next_id(self.node.entry.name + "_ufunc_def")
|
| 140 |
+
|
| 141 |
+
will_be_called_without_gil = not (any(t.is_pyobject for t in arg_types) or
|
| 142 |
+
any(t.is_pyobject for t in out_types))
|
| 143 |
+
|
| 144 |
+
context = dict(
|
| 145 |
+
func_cname=ufunc_cname,
|
| 146 |
+
in_types=arg_types,
|
| 147 |
+
out_types=out_types,
|
| 148 |
+
inline_func_call=self.node.entry.cname,
|
| 149 |
+
inline_func_declaration=inline_func_decl,
|
| 150 |
+
nogil=self.node.entry.type.nogil,
|
| 151 |
+
will_be_called_without_gil=will_be_called_without_gil,
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
code = CythonUtilityCode.load(
|
| 155 |
+
"UFuncDefinition",
|
| 156 |
+
"UFuncs.pyx",
|
| 157 |
+
context=context,
|
| 158 |
+
outer_module_scope=self.global_scope,
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
tree = code.get_tree(entries_only=True)
|
| 162 |
+
return tree
|
| 163 |
+
|
| 164 |
+
def use_generic_utility_code(self):
|
| 165 |
+
# use the invariant C utility code
|
| 166 |
+
self.global_scope.use_utility_code(
|
| 167 |
+
UtilityCode.load_cached("UFuncsInit", "UFuncs_C.c")
|
| 168 |
+
)
|
| 169 |
+
self.global_scope.use_utility_code(
|
| 170 |
+
UtilityCode.load_cached("NumpyImportUFunc", "NumpyImportArray.c")
|
| 171 |
+
)
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
def convert_to_ufunc(node):
|
| 175 |
+
if isinstance(node, Nodes.CFuncDefNode):
|
| 176 |
+
if node.local_scope.parent_scope.is_c_class_scope:
|
| 177 |
+
error(node.pos, "Methods cannot currently be converted to a ufunc")
|
| 178 |
+
return node
|
| 179 |
+
converters = [UFuncConversion(node)]
|
| 180 |
+
original_node = node
|
| 181 |
+
elif isinstance(node, FusedNode.FusedCFuncDefNode) and isinstance(
|
| 182 |
+
node.node, Nodes.CFuncDefNode
|
| 183 |
+
):
|
| 184 |
+
if node.node.local_scope.parent_scope.is_c_class_scope:
|
| 185 |
+
error(node.pos, "Methods cannot currently be converted to a ufunc")
|
| 186 |
+
return node
|
| 187 |
+
converters = [UFuncConversion(n) for n in node.nodes]
|
| 188 |
+
original_node = node.node
|
| 189 |
+
else:
|
| 190 |
+
error(node.pos, "Only C functions can be converted to a ufunc")
|
| 191 |
+
return node
|
| 192 |
+
|
| 193 |
+
if not converters:
|
| 194 |
+
return # this path probably shouldn't happen
|
| 195 |
+
|
| 196 |
+
del converters[0].global_scope.entries[original_node.entry.name]
|
| 197 |
+
# the generic utility code is generic, so there's no reason to do it multiple times
|
| 198 |
+
converters[0].use_generic_utility_code()
|
| 199 |
+
return [node] + _generate_stats_from_converters(converters, original_node)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def generate_ufunc_initialization(converters, cfunc_nodes, original_node):
|
| 203 |
+
global_scope = converters[0].global_scope
|
| 204 |
+
ufunc_funcs_name = global_scope.next_id(Naming.pyrex_prefix + "funcs")
|
| 205 |
+
ufunc_types_name = global_scope.next_id(Naming.pyrex_prefix + "types")
|
| 206 |
+
ufunc_data_name = global_scope.next_id(Naming.pyrex_prefix + "data")
|
| 207 |
+
type_constants = []
|
| 208 |
+
narg_in = None
|
| 209 |
+
narg_out = None
|
| 210 |
+
for c in converters:
|
| 211 |
+
in_const = [d.type_constant for d in c.in_definitions]
|
| 212 |
+
if narg_in is not None:
|
| 213 |
+
assert narg_in == len(in_const)
|
| 214 |
+
else:
|
| 215 |
+
narg_in = len(in_const)
|
| 216 |
+
type_constants.extend(in_const)
|
| 217 |
+
out_const = [d.type_constant for d in c.out_definitions]
|
| 218 |
+
if narg_out is not None:
|
| 219 |
+
assert narg_out == len(out_const)
|
| 220 |
+
else:
|
| 221 |
+
narg_out = len(out_const)
|
| 222 |
+
type_constants.extend(out_const)
|
| 223 |
+
|
| 224 |
+
func_cnames = [cfnode.entry.cname for cfnode in cfunc_nodes]
|
| 225 |
+
|
| 226 |
+
context = dict(
|
| 227 |
+
ufunc_funcs_name=ufunc_funcs_name,
|
| 228 |
+
func_cnames=func_cnames,
|
| 229 |
+
ufunc_types_name=ufunc_types_name,
|
| 230 |
+
type_constants=type_constants,
|
| 231 |
+
ufunc_data_name=ufunc_data_name,
|
| 232 |
+
)
|
| 233 |
+
global_scope.use_utility_code(
|
| 234 |
+
TempitaUtilityCode.load("UFuncConsts", "UFuncs_C.c", context=context)
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
pos = original_node.pos
|
| 238 |
+
func_name = original_node.entry.name
|
| 239 |
+
docstr = original_node.doc
|
| 240 |
+
args_to_func = '%s(), %s, %s(), %s, %s, %s, PyUFunc_None, "%s", %s, 0' % (
|
| 241 |
+
ufunc_funcs_name,
|
| 242 |
+
ufunc_data_name,
|
| 243 |
+
ufunc_types_name,
|
| 244 |
+
len(func_cnames),
|
| 245 |
+
narg_in,
|
| 246 |
+
narg_out,
|
| 247 |
+
func_name,
|
| 248 |
+
docstr.as_c_string_literal() if docstr else "NULL",
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
call_node = ExprNodes.PythonCapiCallNode(
|
| 252 |
+
pos,
|
| 253 |
+
function_name="PyUFunc_FromFuncAndData",
|
| 254 |
+
# use a dummy type because it's honestly too fiddly
|
| 255 |
+
func_type=PyrexTypes.CFuncType(
|
| 256 |
+
PyrexTypes.py_object_type,
|
| 257 |
+
[PyrexTypes.CFuncTypeArg("dummy", PyrexTypes.c_void_ptr_type, None)],
|
| 258 |
+
),
|
| 259 |
+
args=[
|
| 260 |
+
ExprNodes.ConstNode(
|
| 261 |
+
pos, type=PyrexTypes.c_void_ptr_type, value=args_to_func
|
| 262 |
+
)
|
| 263 |
+
],
|
| 264 |
+
)
|
| 265 |
+
lhs_entry = global_scope.declare_var(func_name, PyrexTypes.py_object_type, pos)
|
| 266 |
+
assgn_node = Nodes.SingleAssignmentNode(
|
| 267 |
+
pos,
|
| 268 |
+
lhs=ExprNodes.NameNode(
|
| 269 |
+
pos, name=func_name, type=PyrexTypes.py_object_type, entry=lhs_entry
|
| 270 |
+
),
|
| 271 |
+
rhs=call_node,
|
| 272 |
+
)
|
| 273 |
+
return assgn_node
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
def _generate_stats_from_converters(converters, node):
|
| 277 |
+
stats = []
|
| 278 |
+
for converter in converters:
|
| 279 |
+
tree = converter.generate_cy_utility_code()
|
| 280 |
+
ufunc_node = get_cfunc_from_tree(tree)
|
| 281 |
+
# merge in any utility code
|
| 282 |
+
converter.global_scope.utility_code_list.extend(tree.scope.utility_code_list)
|
| 283 |
+
stats.append(ufunc_node)
|
| 284 |
+
|
| 285 |
+
stats.append(generate_ufunc_initialization(converters, stats, node))
|
| 286 |
+
return stats
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/UtilNodes.py
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
from __future__ import absolute_import
|
| 8 |
+
|
| 9 |
+
from . import Nodes
|
| 10 |
+
from . import ExprNodes
|
| 11 |
+
from .Nodes import Node
|
| 12 |
+
from .ExprNodes import AtomicExprNode
|
| 13 |
+
from .PyrexTypes import c_ptr_type, c_bint_type
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class TempHandle(object):
|
| 17 |
+
# THIS IS DEPRECATED, USE LetRefNode instead
|
| 18 |
+
temp = None
|
| 19 |
+
needs_xdecref = False
|
| 20 |
+
def __init__(self, type, needs_cleanup=None):
|
| 21 |
+
self.type = type
|
| 22 |
+
if needs_cleanup is None:
|
| 23 |
+
self.needs_cleanup = type.is_pyobject
|
| 24 |
+
else:
|
| 25 |
+
self.needs_cleanup = needs_cleanup
|
| 26 |
+
|
| 27 |
+
def ref(self, pos):
|
| 28 |
+
return TempRefNode(pos, handle=self, type=self.type)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class TempRefNode(AtomicExprNode):
|
| 32 |
+
# THIS IS DEPRECATED, USE LetRefNode instead
|
| 33 |
+
# handle TempHandle
|
| 34 |
+
|
| 35 |
+
def analyse_types(self, env):
|
| 36 |
+
assert self.type == self.handle.type
|
| 37 |
+
return self
|
| 38 |
+
|
| 39 |
+
def analyse_target_types(self, env):
|
| 40 |
+
assert self.type == self.handle.type
|
| 41 |
+
return self
|
| 42 |
+
|
| 43 |
+
def analyse_target_declaration(self, env):
|
| 44 |
+
pass
|
| 45 |
+
|
| 46 |
+
def calculate_result_code(self):
|
| 47 |
+
result = self.handle.temp
|
| 48 |
+
if result is None: result = "<error>" # might be called and overwritten
|
| 49 |
+
return result
|
| 50 |
+
|
| 51 |
+
def generate_result_code(self, code):
|
| 52 |
+
pass
|
| 53 |
+
|
| 54 |
+
def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
|
| 55 |
+
if self.type.is_pyobject:
|
| 56 |
+
rhs.make_owned_reference(code)
|
| 57 |
+
# TODO: analyse control flow to see if this is necessary
|
| 58 |
+
code.put_xdecref(self.result(), self.ctype())
|
| 59 |
+
code.putln('%s = %s;' % (
|
| 60 |
+
self.result(),
|
| 61 |
+
rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
|
| 62 |
+
))
|
| 63 |
+
rhs.generate_post_assignment_code(code)
|
| 64 |
+
rhs.free_temps(code)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class TempsBlockNode(Node):
|
| 68 |
+
# THIS IS DEPRECATED, USE LetNode instead
|
| 69 |
+
|
| 70 |
+
"""
|
| 71 |
+
Creates a block which allocates temporary variables.
|
| 72 |
+
This is used by transforms to output constructs that need
|
| 73 |
+
to make use of a temporary variable. Simply pass the types
|
| 74 |
+
of the needed temporaries to the constructor.
|
| 75 |
+
|
| 76 |
+
The variables can be referred to using a TempRefNode
|
| 77 |
+
(which can be constructed by calling get_ref_node).
|
| 78 |
+
"""
|
| 79 |
+
|
| 80 |
+
# temps [TempHandle]
|
| 81 |
+
# body StatNode
|
| 82 |
+
|
| 83 |
+
child_attrs = ["body"]
|
| 84 |
+
|
| 85 |
+
def generate_execution_code(self, code):
|
| 86 |
+
for handle in self.temps:
|
| 87 |
+
handle.temp = code.funcstate.allocate_temp(
|
| 88 |
+
handle.type, manage_ref=handle.needs_cleanup)
|
| 89 |
+
self.body.generate_execution_code(code)
|
| 90 |
+
for handle in self.temps:
|
| 91 |
+
if handle.needs_cleanup:
|
| 92 |
+
if handle.needs_xdecref:
|
| 93 |
+
code.put_xdecref_clear(handle.temp, handle.type)
|
| 94 |
+
else:
|
| 95 |
+
code.put_decref_clear(handle.temp, handle.type)
|
| 96 |
+
code.funcstate.release_temp(handle.temp)
|
| 97 |
+
|
| 98 |
+
def analyse_declarations(self, env):
|
| 99 |
+
self.body.analyse_declarations(env)
|
| 100 |
+
|
| 101 |
+
def analyse_expressions(self, env):
|
| 102 |
+
self.body = self.body.analyse_expressions(env)
|
| 103 |
+
return self
|
| 104 |
+
|
| 105 |
+
def generate_function_definitions(self, env, code):
|
| 106 |
+
self.body.generate_function_definitions(env, code)
|
| 107 |
+
|
| 108 |
+
def annotate(self, code):
|
| 109 |
+
self.body.annotate(code)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
class ResultRefNode(AtomicExprNode):
|
| 113 |
+
# A reference to the result of an expression. The result_code
|
| 114 |
+
# must be set externally (usually a temp name).
|
| 115 |
+
|
| 116 |
+
subexprs = []
|
| 117 |
+
lhs_of_first_assignment = False
|
| 118 |
+
|
| 119 |
+
def __init__(self, expression=None, pos=None, type=None, may_hold_none=True, is_temp=False):
|
| 120 |
+
self.expression = expression
|
| 121 |
+
self.pos = None
|
| 122 |
+
self.may_hold_none = may_hold_none
|
| 123 |
+
if expression is not None:
|
| 124 |
+
self.pos = expression.pos
|
| 125 |
+
self.type = getattr(expression, "type", None)
|
| 126 |
+
if pos is not None:
|
| 127 |
+
self.pos = pos
|
| 128 |
+
if type is not None:
|
| 129 |
+
self.type = type
|
| 130 |
+
if is_temp:
|
| 131 |
+
self.is_temp = True
|
| 132 |
+
assert self.pos is not None
|
| 133 |
+
|
| 134 |
+
def clone_node(self):
|
| 135 |
+
# nothing to do here
|
| 136 |
+
return self
|
| 137 |
+
|
| 138 |
+
def type_dependencies(self, env):
|
| 139 |
+
if self.expression:
|
| 140 |
+
return self.expression.type_dependencies(env)
|
| 141 |
+
else:
|
| 142 |
+
return ()
|
| 143 |
+
|
| 144 |
+
def update_expression(self, expression):
|
| 145 |
+
self.expression = expression
|
| 146 |
+
type = getattr(expression, "type", None)
|
| 147 |
+
if type:
|
| 148 |
+
self.type = type
|
| 149 |
+
|
| 150 |
+
def analyse_target_declaration(self, env):
|
| 151 |
+
pass # OK - we can assign to this
|
| 152 |
+
|
| 153 |
+
def analyse_types(self, env):
|
| 154 |
+
if self.expression is not None:
|
| 155 |
+
if not self.expression.type:
|
| 156 |
+
self.expression = self.expression.analyse_types(env)
|
| 157 |
+
self.type = self.expression.type
|
| 158 |
+
return self
|
| 159 |
+
|
| 160 |
+
def infer_type(self, env):
|
| 161 |
+
if self.type is not None:
|
| 162 |
+
return self.type
|
| 163 |
+
if self.expression is not None:
|
| 164 |
+
if self.expression.type is not None:
|
| 165 |
+
return self.expression.type
|
| 166 |
+
return self.expression.infer_type(env)
|
| 167 |
+
assert False, "cannot infer type of ResultRefNode"
|
| 168 |
+
|
| 169 |
+
def may_be_none(self):
|
| 170 |
+
if not self.type.is_pyobject:
|
| 171 |
+
return False
|
| 172 |
+
return self.may_hold_none
|
| 173 |
+
|
| 174 |
+
def _DISABLED_may_be_none(self):
|
| 175 |
+
# not sure if this is safe - the expression may not be the
|
| 176 |
+
# only value that gets assigned
|
| 177 |
+
if self.expression is not None:
|
| 178 |
+
return self.expression.may_be_none()
|
| 179 |
+
if self.type is not None:
|
| 180 |
+
return self.type.is_pyobject
|
| 181 |
+
return True # play it safe
|
| 182 |
+
|
| 183 |
+
def is_simple(self):
|
| 184 |
+
return True
|
| 185 |
+
|
| 186 |
+
def result(self):
|
| 187 |
+
try:
|
| 188 |
+
return self.result_code
|
| 189 |
+
except AttributeError:
|
| 190 |
+
if self.expression is not None:
|
| 191 |
+
self.result_code = self.expression.result()
|
| 192 |
+
return self.result_code
|
| 193 |
+
|
| 194 |
+
def generate_evaluation_code(self, code):
|
| 195 |
+
pass
|
| 196 |
+
|
| 197 |
+
def generate_result_code(self, code):
|
| 198 |
+
pass
|
| 199 |
+
|
| 200 |
+
def generate_disposal_code(self, code):
|
| 201 |
+
pass
|
| 202 |
+
|
| 203 |
+
def generate_assignment_code(self, rhs, code, overloaded_assignment=False):
|
| 204 |
+
if self.type.is_pyobject:
|
| 205 |
+
rhs.make_owned_reference(code)
|
| 206 |
+
if not self.lhs_of_first_assignment:
|
| 207 |
+
code.put_decref(self.result(), self.ctype())
|
| 208 |
+
code.putln('%s = %s;' % (
|
| 209 |
+
self.result(),
|
| 210 |
+
rhs.result() if overloaded_assignment else rhs.result_as(self.ctype()),
|
| 211 |
+
))
|
| 212 |
+
rhs.generate_post_assignment_code(code)
|
| 213 |
+
rhs.free_temps(code)
|
| 214 |
+
|
| 215 |
+
def allocate_temps(self, env):
|
| 216 |
+
pass
|
| 217 |
+
|
| 218 |
+
def release_temp(self, env):
|
| 219 |
+
pass
|
| 220 |
+
|
| 221 |
+
def free_temps(self, code):
|
| 222 |
+
pass
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class LetNodeMixin:
|
| 226 |
+
def set_temp_expr(self, lazy_temp):
|
| 227 |
+
self.lazy_temp = lazy_temp
|
| 228 |
+
self.temp_expression = lazy_temp.expression
|
| 229 |
+
|
| 230 |
+
def setup_temp_expr(self, code):
|
| 231 |
+
self.temp_expression.generate_evaluation_code(code)
|
| 232 |
+
self.temp_type = self.temp_expression.type
|
| 233 |
+
if self.temp_type.is_array:
|
| 234 |
+
self.temp_type = c_ptr_type(self.temp_type.base_type)
|
| 235 |
+
self._result_in_temp = self.temp_expression.result_in_temp()
|
| 236 |
+
if self._result_in_temp:
|
| 237 |
+
self.temp = self.temp_expression.result()
|
| 238 |
+
else:
|
| 239 |
+
if self.temp_type.is_memoryviewslice:
|
| 240 |
+
self.temp_expression.make_owned_memoryviewslice(code)
|
| 241 |
+
else:
|
| 242 |
+
self.temp_expression.make_owned_reference(code)
|
| 243 |
+
self.temp = code.funcstate.allocate_temp(
|
| 244 |
+
self.temp_type, manage_ref=True)
|
| 245 |
+
code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
|
| 246 |
+
self.temp_expression.generate_disposal_code(code)
|
| 247 |
+
self.temp_expression.free_temps(code)
|
| 248 |
+
self.lazy_temp.result_code = self.temp
|
| 249 |
+
|
| 250 |
+
def teardown_temp_expr(self, code):
|
| 251 |
+
if self._result_in_temp:
|
| 252 |
+
self.temp_expression.generate_disposal_code(code)
|
| 253 |
+
self.temp_expression.free_temps(code)
|
| 254 |
+
else:
|
| 255 |
+
if self.temp_type.needs_refcounting:
|
| 256 |
+
code.put_decref_clear(self.temp, self.temp_type)
|
| 257 |
+
code.funcstate.release_temp(self.temp)
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
|
| 261 |
+
# A wrapper around a subexpression that moves an expression into a
|
| 262 |
+
# temp variable and provides it to the subexpression.
|
| 263 |
+
|
| 264 |
+
subexprs = ['temp_expression', 'subexpression']
|
| 265 |
+
|
| 266 |
+
def __init__(self, lazy_temp, subexpression):
|
| 267 |
+
self.set_temp_expr(lazy_temp)
|
| 268 |
+
self.pos = subexpression.pos
|
| 269 |
+
self.subexpression = subexpression
|
| 270 |
+
# if called after type analysis, we already know the type here
|
| 271 |
+
self.type = self.subexpression.type
|
| 272 |
+
|
| 273 |
+
def infer_type(self, env):
|
| 274 |
+
return self.subexpression.infer_type(env)
|
| 275 |
+
|
| 276 |
+
def may_be_none(self):
|
| 277 |
+
return self.subexpression.may_be_none()
|
| 278 |
+
|
| 279 |
+
def result(self):
|
| 280 |
+
return self.subexpression.result()
|
| 281 |
+
|
| 282 |
+
def analyse_types(self, env):
|
| 283 |
+
self.temp_expression = self.temp_expression.analyse_types(env)
|
| 284 |
+
self.lazy_temp.update_expression(self.temp_expression) # overwrite in case it changed
|
| 285 |
+
self.subexpression = self.subexpression.analyse_types(env)
|
| 286 |
+
self.type = self.subexpression.type
|
| 287 |
+
return self
|
| 288 |
+
|
| 289 |
+
def free_subexpr_temps(self, code):
|
| 290 |
+
self.subexpression.free_temps(code)
|
| 291 |
+
|
| 292 |
+
def generate_subexpr_disposal_code(self, code):
|
| 293 |
+
self.subexpression.generate_disposal_code(code)
|
| 294 |
+
|
| 295 |
+
def generate_evaluation_code(self, code):
|
| 296 |
+
self.setup_temp_expr(code)
|
| 297 |
+
self.subexpression.generate_evaluation_code(code)
|
| 298 |
+
self.teardown_temp_expr(code)
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
LetRefNode = ResultRefNode
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
class LetNode(Nodes.StatNode, LetNodeMixin):
|
| 305 |
+
# Implements a local temporary variable scope. Imagine this
|
| 306 |
+
# syntax being present:
|
| 307 |
+
# let temp = VALUE:
|
| 308 |
+
# BLOCK (can modify temp)
|
| 309 |
+
# if temp is an object, decref
|
| 310 |
+
#
|
| 311 |
+
# Usually used after analysis phase, but forwards analysis methods
|
| 312 |
+
# to its children
|
| 313 |
+
|
| 314 |
+
child_attrs = ['temp_expression', 'body']
|
| 315 |
+
|
| 316 |
+
def __init__(self, lazy_temp, body):
|
| 317 |
+
self.set_temp_expr(lazy_temp)
|
| 318 |
+
self.pos = body.pos
|
| 319 |
+
self.body = body
|
| 320 |
+
|
| 321 |
+
def analyse_declarations(self, env):
|
| 322 |
+
self.temp_expression.analyse_declarations(env)
|
| 323 |
+
self.body.analyse_declarations(env)
|
| 324 |
+
|
| 325 |
+
def analyse_expressions(self, env):
|
| 326 |
+
self.temp_expression = self.temp_expression.analyse_expressions(env)
|
| 327 |
+
self.body = self.body.analyse_expressions(env)
|
| 328 |
+
return self
|
| 329 |
+
|
| 330 |
+
def generate_execution_code(self, code):
|
| 331 |
+
self.setup_temp_expr(code)
|
| 332 |
+
self.body.generate_execution_code(code)
|
| 333 |
+
self.teardown_temp_expr(code)
|
| 334 |
+
|
| 335 |
+
def generate_function_definitions(self, env, code):
|
| 336 |
+
self.temp_expression.generate_function_definitions(env, code)
|
| 337 |
+
self.body.generate_function_definitions(env, code)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
class TempResultFromStatNode(ExprNodes.ExprNode):
|
| 341 |
+
# An ExprNode wrapper around a StatNode that executes the StatNode
|
| 342 |
+
# body. Requires a ResultRefNode that it sets up to refer to its
|
| 343 |
+
# own temp result. The StatNode must assign a value to the result
|
| 344 |
+
# node, which then becomes the result of this node.
|
| 345 |
+
|
| 346 |
+
subexprs = []
|
| 347 |
+
child_attrs = ['body']
|
| 348 |
+
|
| 349 |
+
def __init__(self, result_ref, body):
|
| 350 |
+
self.result_ref = result_ref
|
| 351 |
+
self.pos = body.pos
|
| 352 |
+
self.body = body
|
| 353 |
+
self.type = result_ref.type
|
| 354 |
+
self.is_temp = 1
|
| 355 |
+
|
| 356 |
+
def analyse_declarations(self, env):
|
| 357 |
+
self.body.analyse_declarations(env)
|
| 358 |
+
|
| 359 |
+
def analyse_types(self, env):
|
| 360 |
+
self.body = self.body.analyse_expressions(env)
|
| 361 |
+
return self
|
| 362 |
+
|
| 363 |
+
def may_be_none(self):
|
| 364 |
+
return self.result_ref.may_be_none()
|
| 365 |
+
|
| 366 |
+
def generate_result_code(self, code):
|
| 367 |
+
self.result_ref.result_code = self.result()
|
| 368 |
+
self.body.generate_execution_code(code)
|
| 369 |
+
|
| 370 |
+
def generate_function_definitions(self, env, code):
|
| 371 |
+
self.body.generate_function_definitions(env, code)
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
class HasGilNode(AtomicExprNode):
|
| 375 |
+
"""
|
| 376 |
+
Simple node that evaluates to 0 or 1 depending on whether we're
|
| 377 |
+
in a nogil context
|
| 378 |
+
"""
|
| 379 |
+
type = c_bint_type
|
| 380 |
+
|
| 381 |
+
def analyse_types(self, env):
|
| 382 |
+
return self
|
| 383 |
+
|
| 384 |
+
def generate_result_code(self, code):
|
| 385 |
+
self.has_gil = code.funcstate.gil_owned
|
| 386 |
+
|
| 387 |
+
def calculate_result_code(self):
|
| 388 |
+
return "1" if self.has_gil else "0"
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Visitor.py
ADDED
|
@@ -0,0 +1,871 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cython: infer_types=True
|
| 2 |
+
# cython: language_level=3str
|
| 3 |
+
# cython: auto_pickle=False
|
| 4 |
+
|
| 5 |
+
#
|
| 6 |
+
# Tree visitor and transform framework
|
| 7 |
+
#
|
| 8 |
+
|
| 9 |
+
from __future__ import absolute_import, print_function
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
import inspect
|
| 13 |
+
|
| 14 |
+
from . import TypeSlots
|
| 15 |
+
from . import Builtin
|
| 16 |
+
from . import Nodes
|
| 17 |
+
from . import ExprNodes
|
| 18 |
+
from . import Errors
|
| 19 |
+
from . import DebugFlags
|
| 20 |
+
from . import Future
|
| 21 |
+
|
| 22 |
+
import cython
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
cython.declare(_PRINTABLE=tuple)
|
| 26 |
+
|
| 27 |
+
if sys.version_info[0] >= 3:
|
| 28 |
+
_PRINTABLE = (bytes, str, int, float)
|
| 29 |
+
else:
|
| 30 |
+
_PRINTABLE = (str, unicode, long, int, float)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class TreeVisitor(object):
|
| 34 |
+
"""
|
| 35 |
+
Base class for writing visitors for a Cython tree, contains utilities for
|
| 36 |
+
recursing such trees using visitors. Each node is
|
| 37 |
+
expected to have a child_attrs iterable containing the names of attributes
|
| 38 |
+
containing child nodes or lists of child nodes. Lists are not considered
|
| 39 |
+
part of the tree structure (i.e. contained nodes are considered direct
|
| 40 |
+
children of the parent node).
|
| 41 |
+
|
| 42 |
+
visit_children visits each of the children of a given node (see the visit_children
|
| 43 |
+
documentation). When recursing the tree using visit_children, an attribute
|
| 44 |
+
access_path is maintained which gives information about the current location
|
| 45 |
+
in the tree as a stack of tuples: (parent_node, attrname, index), representing
|
| 46 |
+
the node, attribute and optional list index that was taken in each step in the path to
|
| 47 |
+
the current node.
|
| 48 |
+
|
| 49 |
+
Example:
|
| 50 |
+
|
| 51 |
+
>>> class SampleNode(object):
|
| 52 |
+
... child_attrs = ["head", "body"]
|
| 53 |
+
... def __init__(self, value, head=None, body=None):
|
| 54 |
+
... self.value = value
|
| 55 |
+
... self.head = head
|
| 56 |
+
... self.body = body
|
| 57 |
+
... def __repr__(self): return "SampleNode(%s)" % self.value
|
| 58 |
+
...
|
| 59 |
+
>>> tree = SampleNode(0, SampleNode(1), [SampleNode(2), SampleNode(3)])
|
| 60 |
+
>>> class MyVisitor(TreeVisitor):
|
| 61 |
+
... def visit_SampleNode(self, node):
|
| 62 |
+
... print("in %s %s" % (node.value, self.access_path))
|
| 63 |
+
... self.visitchildren(node)
|
| 64 |
+
... print("out %s" % node.value)
|
| 65 |
+
...
|
| 66 |
+
>>> MyVisitor().visit(tree)
|
| 67 |
+
in 0 []
|
| 68 |
+
in 1 [(SampleNode(0), 'head', None)]
|
| 69 |
+
out 1
|
| 70 |
+
in 2 [(SampleNode(0), 'body', 0)]
|
| 71 |
+
out 2
|
| 72 |
+
in 3 [(SampleNode(0), 'body', 1)]
|
| 73 |
+
out 3
|
| 74 |
+
out 0
|
| 75 |
+
"""
|
| 76 |
+
def __init__(self):
|
| 77 |
+
super(TreeVisitor, self).__init__()
|
| 78 |
+
self.dispatch_table = {}
|
| 79 |
+
self.access_path = []
|
| 80 |
+
|
| 81 |
+
def dump_node(self, node):
|
| 82 |
+
ignored = list(node.child_attrs or []) + [
|
| 83 |
+
'child_attrs', 'pos', 'gil_message', 'cpp_message', 'subexprs']
|
| 84 |
+
values = []
|
| 85 |
+
pos = getattr(node, 'pos', None)
|
| 86 |
+
if pos:
|
| 87 |
+
source = pos[0]
|
| 88 |
+
if source:
|
| 89 |
+
import os.path
|
| 90 |
+
source = os.path.basename(source.get_description())
|
| 91 |
+
values.append(u'%s:%s:%s' % (source, pos[1], pos[2]))
|
| 92 |
+
attribute_names = dir(node)
|
| 93 |
+
for attr in attribute_names:
|
| 94 |
+
if attr in ignored:
|
| 95 |
+
continue
|
| 96 |
+
if attr.startswith('_') or attr.endswith('_'):
|
| 97 |
+
continue
|
| 98 |
+
try:
|
| 99 |
+
value = getattr(node, attr)
|
| 100 |
+
except AttributeError:
|
| 101 |
+
continue
|
| 102 |
+
if value is None or value == 0:
|
| 103 |
+
continue
|
| 104 |
+
elif isinstance(value, list):
|
| 105 |
+
value = u'[...]/%d' % len(value)
|
| 106 |
+
elif not isinstance(value, _PRINTABLE):
|
| 107 |
+
continue
|
| 108 |
+
else:
|
| 109 |
+
value = repr(value)
|
| 110 |
+
values.append(u'%s = %s' % (attr, value))
|
| 111 |
+
return u'%s(%s)' % (node.__class__.__name__, u',\n '.join(values))
|
| 112 |
+
|
| 113 |
+
def _find_node_path(self, stacktrace):
|
| 114 |
+
import os.path
|
| 115 |
+
last_traceback = stacktrace
|
| 116 |
+
nodes = []
|
| 117 |
+
while hasattr(stacktrace, 'tb_frame'):
|
| 118 |
+
frame = stacktrace.tb_frame
|
| 119 |
+
node = frame.f_locals.get('self')
|
| 120 |
+
if isinstance(node, Nodes.Node):
|
| 121 |
+
code = frame.f_code
|
| 122 |
+
method_name = code.co_name
|
| 123 |
+
pos = (os.path.basename(code.co_filename),
|
| 124 |
+
frame.f_lineno)
|
| 125 |
+
nodes.append((node, method_name, pos))
|
| 126 |
+
last_traceback = stacktrace
|
| 127 |
+
stacktrace = stacktrace.tb_next
|
| 128 |
+
return (last_traceback, nodes)
|
| 129 |
+
|
| 130 |
+
def _raise_compiler_error(self, child, e):
|
| 131 |
+
trace = ['']
|
| 132 |
+
for parent, attribute, index in self.access_path:
|
| 133 |
+
node = getattr(parent, attribute)
|
| 134 |
+
if index is None:
|
| 135 |
+
index = ''
|
| 136 |
+
else:
|
| 137 |
+
node = node[index]
|
| 138 |
+
index = u'[%d]' % index
|
| 139 |
+
trace.append(u'%s.%s%s = %s' % (
|
| 140 |
+
parent.__class__.__name__, attribute, index,
|
| 141 |
+
self.dump_node(node)))
|
| 142 |
+
stacktrace, called_nodes = self._find_node_path(sys.exc_info()[2])
|
| 143 |
+
last_node = child
|
| 144 |
+
for node, method_name, pos in called_nodes:
|
| 145 |
+
last_node = node
|
| 146 |
+
trace.append(u"File '%s', line %d, in %s: %s" % (
|
| 147 |
+
pos[0], pos[1], method_name, self.dump_node(node)))
|
| 148 |
+
raise Errors.CompilerCrash(
|
| 149 |
+
getattr(last_node, 'pos', None), self.__class__.__name__,
|
| 150 |
+
u'\n'.join(trace), e, stacktrace)
|
| 151 |
+
|
| 152 |
+
@cython.final
|
| 153 |
+
def find_handler(self, obj):
|
| 154 |
+
# to resolve, try entire hierarchy
|
| 155 |
+
cls = type(obj)
|
| 156 |
+
mro = inspect.getmro(cls)
|
| 157 |
+
for mro_cls in mro:
|
| 158 |
+
handler_method = getattr(self, "visit_" + mro_cls.__name__, None)
|
| 159 |
+
if handler_method is not None:
|
| 160 |
+
return handler_method
|
| 161 |
+
|
| 162 |
+
print(type(self), cls)
|
| 163 |
+
if self.access_path:
|
| 164 |
+
print(self.access_path)
|
| 165 |
+
print(self.access_path[-1][0].pos)
|
| 166 |
+
print(self.access_path[-1][0].__dict__)
|
| 167 |
+
raise RuntimeError("Visitor %r does not accept object: %s" % (self, obj))
|
| 168 |
+
|
| 169 |
+
def visit(self, obj):
|
| 170 |
+
# generic def entry point for calls from Python subclasses
|
| 171 |
+
return self._visit(obj)
|
| 172 |
+
|
| 173 |
+
@cython.final
|
| 174 |
+
def _visit(self, obj):
|
| 175 |
+
# fast cdef entry point for calls from Cython subclasses
|
| 176 |
+
try:
|
| 177 |
+
try:
|
| 178 |
+
handler_method = self.dispatch_table[type(obj)]
|
| 179 |
+
except KeyError:
|
| 180 |
+
handler_method = self.find_handler(obj)
|
| 181 |
+
self.dispatch_table[type(obj)] = handler_method
|
| 182 |
+
return handler_method(obj)
|
| 183 |
+
except Errors.CompileError:
|
| 184 |
+
raise
|
| 185 |
+
except Errors.AbortError:
|
| 186 |
+
raise
|
| 187 |
+
except Exception as e:
|
| 188 |
+
if DebugFlags.debug_no_exception_intercept:
|
| 189 |
+
raise
|
| 190 |
+
self._raise_compiler_error(obj, e)
|
| 191 |
+
|
| 192 |
+
@cython.final
|
| 193 |
+
def _visitchild(self, child, parent, attrname, idx):
|
| 194 |
+
# fast cdef entry point for calls from Cython subclasses
|
| 195 |
+
self.access_path.append((parent, attrname, idx))
|
| 196 |
+
result = self._visit(child)
|
| 197 |
+
self.access_path.pop()
|
| 198 |
+
return result
|
| 199 |
+
|
| 200 |
+
def visitchildren(self, parent, attrs=None, exclude=None):
|
| 201 |
+
# generic def entry point for calls from Python subclasses
|
| 202 |
+
return self._visitchildren(parent, attrs, exclude)
|
| 203 |
+
|
| 204 |
+
@cython.final
|
| 205 |
+
@cython.locals(idx=cython.Py_ssize_t)
|
| 206 |
+
def _visitchildren(self, parent, attrs, exclude):
|
| 207 |
+
# fast cdef entry point for calls from Cython subclasses
|
| 208 |
+
"""
|
| 209 |
+
Visits the children of the given parent. If parent is None, returns
|
| 210 |
+
immediately (returning None).
|
| 211 |
+
|
| 212 |
+
The return value is a dictionary giving the results for each
|
| 213 |
+
child (mapping the attribute name to either the return value
|
| 214 |
+
or a list of return values (in the case of multiple children
|
| 215 |
+
in an attribute)).
|
| 216 |
+
"""
|
| 217 |
+
if parent is None: return None
|
| 218 |
+
result = {}
|
| 219 |
+
for attr in parent.child_attrs:
|
| 220 |
+
if attrs is not None and attr not in attrs: continue
|
| 221 |
+
if exclude is not None and attr in exclude: continue
|
| 222 |
+
child = getattr(parent, attr)
|
| 223 |
+
if child is not None:
|
| 224 |
+
if type(child) is list:
|
| 225 |
+
childretval = [self._visitchild(x, parent, attr, idx) for idx, x in enumerate(child)]
|
| 226 |
+
else:
|
| 227 |
+
childretval = self._visitchild(child, parent, attr, None)
|
| 228 |
+
assert not isinstance(childretval, list), 'Cannot insert list here: %s in %r' % (attr, parent)
|
| 229 |
+
result[attr] = childretval
|
| 230 |
+
return result
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
class VisitorTransform(TreeVisitor):
|
| 234 |
+
"""
|
| 235 |
+
A tree transform is a base class for visitors that wants to do stream
|
| 236 |
+
processing of the structure (rather than attributes etc.) of a tree.
|
| 237 |
+
|
| 238 |
+
It implements __call__ to simply visit the argument node.
|
| 239 |
+
|
| 240 |
+
It requires the visitor methods to return the nodes which should take
|
| 241 |
+
the place of the visited node in the result tree (which can be the same
|
| 242 |
+
or one or more replacement). Specifically, if the return value from
|
| 243 |
+
a visitor method is:
|
| 244 |
+
|
| 245 |
+
- [] or None; the visited node will be removed (set to None if an attribute and
|
| 246 |
+
removed if in a list)
|
| 247 |
+
- A single node; the visited node will be replaced by the returned node.
|
| 248 |
+
- A list of nodes; the visited nodes will be replaced by all the nodes in the
|
| 249 |
+
list. This will only work if the node was already a member of a list; if it
|
| 250 |
+
was not, an exception will be raised. (Typically you want to ensure that you
|
| 251 |
+
are within a StatListNode or similar before doing this.)
|
| 252 |
+
"""
|
| 253 |
+
def visitchildren(self, parent, attrs=None, exclude=None):
|
| 254 |
+
# generic def entry point for calls from Python subclasses
|
| 255 |
+
return self._process_children(parent, attrs, exclude)
|
| 256 |
+
|
| 257 |
+
@cython.final
|
| 258 |
+
def _process_children(self, parent, attrs=None, exclude=None):
|
| 259 |
+
# fast cdef entry point for calls from Cython subclasses
|
| 260 |
+
result = self._visitchildren(parent, attrs, exclude)
|
| 261 |
+
for attr, newnode in result.items():
|
| 262 |
+
if type(newnode) is list:
|
| 263 |
+
newnode = self._flatten_list(newnode)
|
| 264 |
+
setattr(parent, attr, newnode)
|
| 265 |
+
return result
|
| 266 |
+
|
| 267 |
+
@cython.final
|
| 268 |
+
def _flatten_list(self, orig_list):
|
| 269 |
+
# Flatten the list one level and remove any None
|
| 270 |
+
newlist = []
|
| 271 |
+
for x in orig_list:
|
| 272 |
+
if x is not None:
|
| 273 |
+
if type(x) is list:
|
| 274 |
+
newlist.extend(x)
|
| 275 |
+
else:
|
| 276 |
+
newlist.append(x)
|
| 277 |
+
return newlist
|
| 278 |
+
|
| 279 |
+
def visitchild(self, parent, attr, idx=0):
|
| 280 |
+
# Helper to visit specific children from Python subclasses
|
| 281 |
+
child = getattr(parent, attr)
|
| 282 |
+
if child is not None:
|
| 283 |
+
node = self._visitchild(child, parent, attr, idx)
|
| 284 |
+
if node is not child:
|
| 285 |
+
setattr(parent, attr, node)
|
| 286 |
+
child = node
|
| 287 |
+
return child
|
| 288 |
+
|
| 289 |
+
def recurse_to_children(self, node):
|
| 290 |
+
self._process_children(node)
|
| 291 |
+
return node
|
| 292 |
+
|
| 293 |
+
def __call__(self, root):
|
| 294 |
+
return self._visit(root)
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
class CythonTransform(VisitorTransform):
|
| 298 |
+
"""
|
| 299 |
+
Certain common conventions and utilities for Cython transforms.
|
| 300 |
+
|
| 301 |
+
- Sets up the context of the pipeline in self.context
|
| 302 |
+
- Tracks directives in effect in self.current_directives
|
| 303 |
+
"""
|
| 304 |
+
def __init__(self, context):
|
| 305 |
+
super(CythonTransform, self).__init__()
|
| 306 |
+
self.context = context
|
| 307 |
+
|
| 308 |
+
def __call__(self, node):
|
| 309 |
+
from .ModuleNode import ModuleNode
|
| 310 |
+
if isinstance(node, ModuleNode):
|
| 311 |
+
self.current_directives = node.directives
|
| 312 |
+
return super(CythonTransform, self).__call__(node)
|
| 313 |
+
|
| 314 |
+
def visit_CompilerDirectivesNode(self, node):
|
| 315 |
+
old = self.current_directives
|
| 316 |
+
self.current_directives = node.directives
|
| 317 |
+
self._process_children(node)
|
| 318 |
+
self.current_directives = old
|
| 319 |
+
return node
|
| 320 |
+
|
| 321 |
+
def visit_Node(self, node):
|
| 322 |
+
self._process_children(node)
|
| 323 |
+
return node
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
class ScopeTrackingTransform(CythonTransform):
|
| 327 |
+
# Keeps track of type of scopes
|
| 328 |
+
#scope_type: can be either of 'module', 'function', 'cclass', 'pyclass', 'struct'
|
| 329 |
+
#scope_node: the node that owns the current scope
|
| 330 |
+
|
| 331 |
+
def visit_ModuleNode(self, node):
|
| 332 |
+
self.scope_type = 'module'
|
| 333 |
+
self.scope_node = node
|
| 334 |
+
self._process_children(node)
|
| 335 |
+
return node
|
| 336 |
+
|
| 337 |
+
def visit_scope(self, node, scope_type):
|
| 338 |
+
prev = self.scope_type, self.scope_node
|
| 339 |
+
self.scope_type = scope_type
|
| 340 |
+
self.scope_node = node
|
| 341 |
+
self._process_children(node)
|
| 342 |
+
self.scope_type, self.scope_node = prev
|
| 343 |
+
return node
|
| 344 |
+
|
| 345 |
+
def visit_CClassDefNode(self, node):
|
| 346 |
+
return self.visit_scope(node, 'cclass')
|
| 347 |
+
|
| 348 |
+
def visit_PyClassDefNode(self, node):
|
| 349 |
+
return self.visit_scope(node, 'pyclass')
|
| 350 |
+
|
| 351 |
+
def visit_FuncDefNode(self, node):
|
| 352 |
+
return self.visit_scope(node, 'function')
|
| 353 |
+
|
| 354 |
+
def visit_CStructOrUnionDefNode(self, node):
|
| 355 |
+
return self.visit_scope(node, 'struct')
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
class EnvTransform(CythonTransform):
|
| 359 |
+
"""
|
| 360 |
+
This transformation keeps a stack of the environments.
|
| 361 |
+
"""
|
| 362 |
+
def __call__(self, root):
|
| 363 |
+
self.env_stack = []
|
| 364 |
+
self.enter_scope(root, root.scope)
|
| 365 |
+
return super(EnvTransform, self).__call__(root)
|
| 366 |
+
|
| 367 |
+
def current_env(self):
|
| 368 |
+
return self.env_stack[-1][1]
|
| 369 |
+
|
| 370 |
+
def current_scope_node(self):
|
| 371 |
+
return self.env_stack[-1][0]
|
| 372 |
+
|
| 373 |
+
def global_scope(self):
|
| 374 |
+
return self.current_env().global_scope()
|
| 375 |
+
|
| 376 |
+
def enter_scope(self, node, scope):
|
| 377 |
+
self.env_stack.append((node, scope))
|
| 378 |
+
|
| 379 |
+
def exit_scope(self):
|
| 380 |
+
self.env_stack.pop()
|
| 381 |
+
|
| 382 |
+
def visit_FuncDefNode(self, node):
|
| 383 |
+
self.visit_func_outer_attrs(node)
|
| 384 |
+
self.enter_scope(node, node.local_scope)
|
| 385 |
+
self.visitchildren(node, attrs=None, exclude=node.outer_attrs)
|
| 386 |
+
self.exit_scope()
|
| 387 |
+
return node
|
| 388 |
+
|
| 389 |
+
def visit_func_outer_attrs(self, node):
|
| 390 |
+
self.visitchildren(node, attrs=node.outer_attrs)
|
| 391 |
+
|
| 392 |
+
def visit_GeneratorBodyDefNode(self, node):
|
| 393 |
+
self._process_children(node)
|
| 394 |
+
return node
|
| 395 |
+
|
| 396 |
+
def visit_ClassDefNode(self, node):
|
| 397 |
+
self.enter_scope(node, node.scope)
|
| 398 |
+
self._process_children(node)
|
| 399 |
+
self.exit_scope()
|
| 400 |
+
return node
|
| 401 |
+
|
| 402 |
+
def visit_CStructOrUnionDefNode(self, node):
|
| 403 |
+
self.enter_scope(node, node.scope)
|
| 404 |
+
self._process_children(node)
|
| 405 |
+
self.exit_scope()
|
| 406 |
+
return node
|
| 407 |
+
|
| 408 |
+
def visit_ScopedExprNode(self, node):
|
| 409 |
+
if node.expr_scope:
|
| 410 |
+
self.enter_scope(node, node.expr_scope)
|
| 411 |
+
self._process_children(node)
|
| 412 |
+
self.exit_scope()
|
| 413 |
+
else:
|
| 414 |
+
self._process_children(node)
|
| 415 |
+
return node
|
| 416 |
+
|
| 417 |
+
def visit_CArgDeclNode(self, node):
|
| 418 |
+
# default arguments are evaluated in the outer scope
|
| 419 |
+
if node.default:
|
| 420 |
+
attrs = [attr for attr in node.child_attrs if attr != 'default']
|
| 421 |
+
self._process_children(node, attrs)
|
| 422 |
+
self.enter_scope(node, self.current_env().outer_scope)
|
| 423 |
+
self.visitchildren(node, ('default',))
|
| 424 |
+
self.exit_scope()
|
| 425 |
+
else:
|
| 426 |
+
self._process_children(node)
|
| 427 |
+
return node
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
class NodeRefCleanupMixin(object):
|
| 431 |
+
"""
|
| 432 |
+
Clean up references to nodes that were replaced.
|
| 433 |
+
|
| 434 |
+
NOTE: this implementation assumes that the replacement is
|
| 435 |
+
done first, before hitting any further references during
|
| 436 |
+
normal tree traversal. This needs to be arranged by calling
|
| 437 |
+
"self.visitchildren()" at a proper place in the transform
|
| 438 |
+
and by ordering the "child_attrs" of nodes appropriately.
|
| 439 |
+
"""
|
| 440 |
+
def __init__(self, *args):
|
| 441 |
+
super(NodeRefCleanupMixin, self).__init__(*args)
|
| 442 |
+
self._replacements = {}
|
| 443 |
+
|
| 444 |
+
def visit_CloneNode(self, node):
|
| 445 |
+
arg = node.arg
|
| 446 |
+
if arg not in self._replacements:
|
| 447 |
+
self.visitchildren(arg)
|
| 448 |
+
node.arg = self._replacements.get(arg, arg)
|
| 449 |
+
return node
|
| 450 |
+
|
| 451 |
+
def visit_ResultRefNode(self, node):
|
| 452 |
+
expr = node.expression
|
| 453 |
+
if expr is None or expr not in self._replacements:
|
| 454 |
+
self.visitchildren(node)
|
| 455 |
+
expr = node.expression
|
| 456 |
+
if expr is not None:
|
| 457 |
+
node.expression = self._replacements.get(expr, expr)
|
| 458 |
+
return node
|
| 459 |
+
|
| 460 |
+
def replace(self, node, replacement):
|
| 461 |
+
self._replacements[node] = replacement
|
| 462 |
+
return replacement
|
| 463 |
+
|
| 464 |
+
|
| 465 |
+
find_special_method_for_binary_operator = {
|
| 466 |
+
'<': '__lt__',
|
| 467 |
+
'<=': '__le__',
|
| 468 |
+
'==': '__eq__',
|
| 469 |
+
'!=': '__ne__',
|
| 470 |
+
'>=': '__ge__',
|
| 471 |
+
'>': '__gt__',
|
| 472 |
+
'+': '__add__',
|
| 473 |
+
'&': '__and__',
|
| 474 |
+
'/': '__div__',
|
| 475 |
+
'//': '__floordiv__',
|
| 476 |
+
'<<': '__lshift__',
|
| 477 |
+
'%': '__mod__',
|
| 478 |
+
'*': '__mul__',
|
| 479 |
+
'|': '__or__',
|
| 480 |
+
'**': '__pow__',
|
| 481 |
+
'>>': '__rshift__',
|
| 482 |
+
'-': '__sub__',
|
| 483 |
+
'^': '__xor__',
|
| 484 |
+
'in': '__contains__',
|
| 485 |
+
}.get
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
find_special_method_for_unary_operator = {
|
| 489 |
+
'not': '__not__',
|
| 490 |
+
'~': '__inv__',
|
| 491 |
+
'-': '__neg__',
|
| 492 |
+
'+': '__pos__',
|
| 493 |
+
}.get
|
| 494 |
+
|
| 495 |
+
|
| 496 |
+
class MethodDispatcherTransform(EnvTransform):
|
| 497 |
+
"""
|
| 498 |
+
Base class for transformations that want to intercept on specific
|
| 499 |
+
builtin functions or methods of builtin types, including special
|
| 500 |
+
methods triggered by Python operators. Must run after declaration
|
| 501 |
+
analysis when entries were assigned.
|
| 502 |
+
|
| 503 |
+
Naming pattern for handler methods is as follows:
|
| 504 |
+
|
| 505 |
+
* builtin functions: _handle_(general|simple|any)_function_NAME
|
| 506 |
+
|
| 507 |
+
* builtin methods: _handle_(general|simple|any)_method_TYPENAME_METHODNAME
|
| 508 |
+
"""
|
| 509 |
+
# only visit call nodes and Python operations
|
| 510 |
+
def visit_GeneralCallNode(self, node):
|
| 511 |
+
self._process_children(node)
|
| 512 |
+
function = node.function
|
| 513 |
+
if not function.type.is_pyobject:
|
| 514 |
+
return node
|
| 515 |
+
arg_tuple = node.positional_args
|
| 516 |
+
if not isinstance(arg_tuple, ExprNodes.TupleNode):
|
| 517 |
+
return node
|
| 518 |
+
keyword_args = node.keyword_args
|
| 519 |
+
if keyword_args and not isinstance(keyword_args, ExprNodes.DictNode):
|
| 520 |
+
# can't handle **kwargs
|
| 521 |
+
return node
|
| 522 |
+
args = arg_tuple.args
|
| 523 |
+
return self._dispatch_to_handler(node, function, args, keyword_args)
|
| 524 |
+
|
| 525 |
+
def visit_SimpleCallNode(self, node):
|
| 526 |
+
self._process_children(node)
|
| 527 |
+
function = node.function
|
| 528 |
+
if function.type.is_pyobject:
|
| 529 |
+
arg_tuple = node.arg_tuple
|
| 530 |
+
if not isinstance(arg_tuple, ExprNodes.TupleNode):
|
| 531 |
+
return node
|
| 532 |
+
args = arg_tuple.args
|
| 533 |
+
else:
|
| 534 |
+
args = node.args
|
| 535 |
+
return self._dispatch_to_handler(node, function, args, None)
|
| 536 |
+
|
| 537 |
+
def visit_PrimaryCmpNode(self, node):
|
| 538 |
+
if node.cascade:
|
| 539 |
+
# not currently handled below
|
| 540 |
+
self._process_children(node)
|
| 541 |
+
return node
|
| 542 |
+
return self._visit_binop_node(node)
|
| 543 |
+
|
| 544 |
+
def visit_BinopNode(self, node):
|
| 545 |
+
return self._visit_binop_node(node)
|
| 546 |
+
|
| 547 |
+
def _visit_binop_node(self, node):
|
| 548 |
+
self._process_children(node)
|
| 549 |
+
# FIXME: could special case 'not_in'
|
| 550 |
+
special_method_name = find_special_method_for_binary_operator(node.operator)
|
| 551 |
+
if special_method_name:
|
| 552 |
+
operand1, operand2 = node.operand1, node.operand2
|
| 553 |
+
if special_method_name == '__contains__':
|
| 554 |
+
operand1, operand2 = operand2, operand1
|
| 555 |
+
elif special_method_name == '__div__':
|
| 556 |
+
if Future.division in self.current_env().global_scope().context.future_directives:
|
| 557 |
+
special_method_name = '__truediv__'
|
| 558 |
+
obj_type = operand1.type
|
| 559 |
+
if obj_type.is_builtin_type:
|
| 560 |
+
type_name = obj_type.name
|
| 561 |
+
else:
|
| 562 |
+
type_name = "object" # safety measure
|
| 563 |
+
node = self._dispatch_to_method_handler(
|
| 564 |
+
special_method_name, None, False, type_name,
|
| 565 |
+
node, None, [operand1, operand2], None)
|
| 566 |
+
return node
|
| 567 |
+
|
| 568 |
+
def visit_UnopNode(self, node):
|
| 569 |
+
self._process_children(node)
|
| 570 |
+
special_method_name = find_special_method_for_unary_operator(node.operator)
|
| 571 |
+
if special_method_name:
|
| 572 |
+
operand = node.operand
|
| 573 |
+
obj_type = operand.type
|
| 574 |
+
if obj_type.is_builtin_type:
|
| 575 |
+
type_name = obj_type.name
|
| 576 |
+
else:
|
| 577 |
+
type_name = "object" # safety measure
|
| 578 |
+
node = self._dispatch_to_method_handler(
|
| 579 |
+
special_method_name, None, False, type_name,
|
| 580 |
+
node, None, [operand], None)
|
| 581 |
+
return node
|
| 582 |
+
|
| 583 |
+
### dispatch to specific handlers
|
| 584 |
+
|
| 585 |
+
def _find_handler(self, match_name, has_kwargs):
|
| 586 |
+
try:
|
| 587 |
+
match_name.encode('ascii')
|
| 588 |
+
except UnicodeEncodeError:
|
| 589 |
+
# specifically when running the Cython compiler under Python 2
|
| 590 |
+
# getattr can't take a unicode string.
|
| 591 |
+
# Classes with unicode names won't have specific handlers and thus it
|
| 592 |
+
# should be OK to return None.
|
| 593 |
+
# Doing the test here ensures that the same code gets run on
|
| 594 |
+
# Python 2 and 3
|
| 595 |
+
return None
|
| 596 |
+
|
| 597 |
+
call_type = 'general' if has_kwargs else 'simple'
|
| 598 |
+
handler = getattr(self, '_handle_%s_%s' % (call_type, match_name), None)
|
| 599 |
+
if handler is None:
|
| 600 |
+
handler = getattr(self, '_handle_any_%s' % match_name, None)
|
| 601 |
+
return handler
|
| 602 |
+
|
| 603 |
+
def _delegate_to_assigned_value(self, node, function, arg_list, kwargs):
|
| 604 |
+
assignment = function.cf_state[0]
|
| 605 |
+
value = assignment.rhs
|
| 606 |
+
if value.is_name:
|
| 607 |
+
if not value.entry or len(value.entry.cf_assignments) > 1:
|
| 608 |
+
# the variable might have been reassigned => play safe
|
| 609 |
+
return node
|
| 610 |
+
elif value.is_attribute and value.obj.is_name:
|
| 611 |
+
if not value.obj.entry or len(value.obj.entry.cf_assignments) > 1:
|
| 612 |
+
# the underlying variable might have been reassigned => play safe
|
| 613 |
+
return node
|
| 614 |
+
else:
|
| 615 |
+
return node
|
| 616 |
+
return self._dispatch_to_handler(
|
| 617 |
+
node, value, arg_list, kwargs)
|
| 618 |
+
|
| 619 |
+
def _dispatch_to_handler(self, node, function, arg_list, kwargs):
|
| 620 |
+
if function.is_name:
|
| 621 |
+
# we only consider functions that are either builtin
|
| 622 |
+
# Python functions or builtins that were already replaced
|
| 623 |
+
# into a C function call (defined in the builtin scope)
|
| 624 |
+
if not function.entry:
|
| 625 |
+
return node
|
| 626 |
+
entry = function.entry
|
| 627 |
+
is_builtin = (
|
| 628 |
+
entry.is_builtin or
|
| 629 |
+
entry is self.current_env().builtin_scope().lookup_here(function.name))
|
| 630 |
+
if not is_builtin:
|
| 631 |
+
if function.cf_state and function.cf_state.is_single:
|
| 632 |
+
# we know the value of the variable
|
| 633 |
+
# => see if it's usable instead
|
| 634 |
+
return self._delegate_to_assigned_value(
|
| 635 |
+
node, function, arg_list, kwargs)
|
| 636 |
+
if arg_list and entry.is_cmethod and entry.scope and entry.scope.parent_type.is_builtin_type:
|
| 637 |
+
if entry.scope.parent_type is arg_list[0].type:
|
| 638 |
+
# Optimised (unbound) method of a builtin type => try to "de-optimise".
|
| 639 |
+
return self._dispatch_to_method_handler(
|
| 640 |
+
entry.name, self_arg=None, is_unbound_method=True,
|
| 641 |
+
type_name=entry.scope.parent_type.name,
|
| 642 |
+
node=node, function=function, arg_list=arg_list, kwargs=kwargs)
|
| 643 |
+
return node
|
| 644 |
+
function_handler = self._find_handler(
|
| 645 |
+
"function_%s" % function.name, kwargs)
|
| 646 |
+
if function_handler is None:
|
| 647 |
+
return self._handle_function(node, function.name, function, arg_list, kwargs)
|
| 648 |
+
if kwargs:
|
| 649 |
+
return function_handler(node, function, arg_list, kwargs)
|
| 650 |
+
else:
|
| 651 |
+
return function_handler(node, function, arg_list)
|
| 652 |
+
elif function.is_attribute:
|
| 653 |
+
attr_name = function.attribute
|
| 654 |
+
if function.type.is_pyobject:
|
| 655 |
+
self_arg = function.obj
|
| 656 |
+
elif node.self and function.entry:
|
| 657 |
+
entry = function.entry.as_variable
|
| 658 |
+
if not entry or not entry.is_builtin:
|
| 659 |
+
return node
|
| 660 |
+
# C implementation of a Python builtin method - see if we find further matches
|
| 661 |
+
self_arg = node.self
|
| 662 |
+
arg_list = arg_list[1:] # drop CloneNode of self argument
|
| 663 |
+
else:
|
| 664 |
+
return node
|
| 665 |
+
obj_type = self_arg.type
|
| 666 |
+
is_unbound_method = False
|
| 667 |
+
if obj_type.is_builtin_type:
|
| 668 |
+
if obj_type is Builtin.type_type and self_arg.is_name and arg_list and arg_list[0].type.is_pyobject:
|
| 669 |
+
# calling an unbound method like 'list.append(L,x)'
|
| 670 |
+
# (ignoring 'type.mro()' here ...)
|
| 671 |
+
type_name = self_arg.name
|
| 672 |
+
self_arg = None
|
| 673 |
+
is_unbound_method = True
|
| 674 |
+
else:
|
| 675 |
+
type_name = obj_type.name
|
| 676 |
+
else:
|
| 677 |
+
type_name = "object" # safety measure
|
| 678 |
+
return self._dispatch_to_method_handler(
|
| 679 |
+
attr_name, self_arg, is_unbound_method, type_name,
|
| 680 |
+
node, function, arg_list, kwargs)
|
| 681 |
+
else:
|
| 682 |
+
return node
|
| 683 |
+
|
| 684 |
+
def _dispatch_to_method_handler(self, attr_name, self_arg,
|
| 685 |
+
is_unbound_method, type_name,
|
| 686 |
+
node, function, arg_list, kwargs):
|
| 687 |
+
method_handler = self._find_handler(
|
| 688 |
+
"method_%s_%s" % (type_name, attr_name), kwargs)
|
| 689 |
+
if method_handler is None:
|
| 690 |
+
if (attr_name in TypeSlots.special_method_names
|
| 691 |
+
or attr_name in ['__new__', '__class__']):
|
| 692 |
+
method_handler = self._find_handler(
|
| 693 |
+
"slot%s" % attr_name, kwargs)
|
| 694 |
+
if method_handler is None:
|
| 695 |
+
return self._handle_method(
|
| 696 |
+
node, type_name, attr_name, function,
|
| 697 |
+
arg_list, is_unbound_method, kwargs)
|
| 698 |
+
if self_arg is not None:
|
| 699 |
+
arg_list = [self_arg] + list(arg_list)
|
| 700 |
+
if kwargs:
|
| 701 |
+
result = method_handler(
|
| 702 |
+
node, function, arg_list, is_unbound_method, kwargs)
|
| 703 |
+
else:
|
| 704 |
+
result = method_handler(
|
| 705 |
+
node, function, arg_list, is_unbound_method)
|
| 706 |
+
return result
|
| 707 |
+
|
| 708 |
+
def _handle_function(self, node, function_name, function, arg_list, kwargs):
|
| 709 |
+
"""Fallback handler"""
|
| 710 |
+
return node
|
| 711 |
+
|
| 712 |
+
def _handle_method(self, node, type_name, attr_name, function,
|
| 713 |
+
arg_list, is_unbound_method, kwargs):
|
| 714 |
+
"""Fallback handler"""
|
| 715 |
+
return node
|
| 716 |
+
|
| 717 |
+
|
| 718 |
+
class RecursiveNodeReplacer(VisitorTransform):
|
| 719 |
+
"""
|
| 720 |
+
Recursively replace all occurrences of a node in a subtree by
|
| 721 |
+
another node.
|
| 722 |
+
"""
|
| 723 |
+
def __init__(self, orig_node, new_node):
|
| 724 |
+
super(RecursiveNodeReplacer, self).__init__()
|
| 725 |
+
self.orig_node, self.new_node = orig_node, new_node
|
| 726 |
+
|
| 727 |
+
def visit_CloneNode(self, node):
|
| 728 |
+
if node is self.orig_node:
|
| 729 |
+
return self.new_node
|
| 730 |
+
if node.arg is self.orig_node:
|
| 731 |
+
node.arg = self.new_node
|
| 732 |
+
return node
|
| 733 |
+
|
| 734 |
+
def visit_Node(self, node):
|
| 735 |
+
self._process_children(node)
|
| 736 |
+
if node is self.orig_node:
|
| 737 |
+
return self.new_node
|
| 738 |
+
else:
|
| 739 |
+
return node
|
| 740 |
+
|
| 741 |
+
def recursively_replace_node(tree, old_node, new_node):
|
| 742 |
+
replace_in = RecursiveNodeReplacer(old_node, new_node)
|
| 743 |
+
replace_in(tree)
|
| 744 |
+
|
| 745 |
+
|
| 746 |
+
class NodeFinder(TreeVisitor):
|
| 747 |
+
"""
|
| 748 |
+
Find out if a node appears in a subtree.
|
| 749 |
+
"""
|
| 750 |
+
def __init__(self, node):
|
| 751 |
+
super(NodeFinder, self).__init__()
|
| 752 |
+
self.node = node
|
| 753 |
+
self.found = False
|
| 754 |
+
|
| 755 |
+
def visit_Node(self, node):
|
| 756 |
+
if self.found:
|
| 757 |
+
pass # short-circuit
|
| 758 |
+
elif node is self.node:
|
| 759 |
+
self.found = True
|
| 760 |
+
else:
|
| 761 |
+
self._visitchildren(node, None, None)
|
| 762 |
+
|
| 763 |
+
def tree_contains(tree, node):
|
| 764 |
+
finder = NodeFinder(node)
|
| 765 |
+
finder.visit(tree)
|
| 766 |
+
return finder.found
|
| 767 |
+
|
| 768 |
+
|
| 769 |
+
# Utils
|
| 770 |
+
def replace_node(ptr, value):
|
| 771 |
+
"""Replaces a node. ptr is of the form used on the access path stack
|
| 772 |
+
(parent, attrname, listidx|None)
|
| 773 |
+
"""
|
| 774 |
+
parent, attrname, listidx = ptr
|
| 775 |
+
if listidx is None:
|
| 776 |
+
setattr(parent, attrname, value)
|
| 777 |
+
else:
|
| 778 |
+
getattr(parent, attrname)[listidx] = value
|
| 779 |
+
|
| 780 |
+
|
| 781 |
+
class PrintTree(TreeVisitor):
|
| 782 |
+
"""Prints a representation of the tree to standard output.
|
| 783 |
+
Subclass and override repr_of to provide more information
|
| 784 |
+
about nodes. """
|
| 785 |
+
def __init__(self, start=None, end=None):
|
| 786 |
+
TreeVisitor.__init__(self)
|
| 787 |
+
self._indent = ""
|
| 788 |
+
if start is not None or end is not None:
|
| 789 |
+
self._line_range = (start or 0, end or 2**30)
|
| 790 |
+
else:
|
| 791 |
+
self._line_range = None
|
| 792 |
+
|
| 793 |
+
def indent(self):
|
| 794 |
+
self._indent += " "
|
| 795 |
+
|
| 796 |
+
def unindent(self):
|
| 797 |
+
self._indent = self._indent[:-2]
|
| 798 |
+
|
| 799 |
+
def __call__(self, tree, phase=None):
|
| 800 |
+
print("Parse tree dump at phase '%s'" % phase)
|
| 801 |
+
self.visit(tree)
|
| 802 |
+
return tree
|
| 803 |
+
|
| 804 |
+
# Don't do anything about process_list, the defaults gives
|
| 805 |
+
# nice-looking name[idx] nodes which will visually appear
|
| 806 |
+
# under the parent-node, not displaying the list itself in
|
| 807 |
+
# the hierarchy.
|
| 808 |
+
def visit_Node(self, node):
|
| 809 |
+
self._print_node(node)
|
| 810 |
+
self.indent()
|
| 811 |
+
self.visitchildren(node)
|
| 812 |
+
self.unindent()
|
| 813 |
+
return node
|
| 814 |
+
|
| 815 |
+
def visit_CloneNode(self, node):
|
| 816 |
+
self._print_node(node)
|
| 817 |
+
self.indent()
|
| 818 |
+
line = node.pos[1]
|
| 819 |
+
if self._line_range is None or self._line_range[0] <= line <= self._line_range[1]:
|
| 820 |
+
print("%s- %s: %s" % (self._indent, 'arg', self.repr_of(node.arg)))
|
| 821 |
+
self.indent()
|
| 822 |
+
self.visitchildren(node.arg)
|
| 823 |
+
self.unindent()
|
| 824 |
+
self.unindent()
|
| 825 |
+
return node
|
| 826 |
+
|
| 827 |
+
def _print_node(self, node):
|
| 828 |
+
line = node.pos[1]
|
| 829 |
+
if self._line_range is None or self._line_range[0] <= line <= self._line_range[1]:
|
| 830 |
+
if len(self.access_path) == 0:
|
| 831 |
+
name = "(root)"
|
| 832 |
+
else:
|
| 833 |
+
parent, attr, idx = self.access_path[-1]
|
| 834 |
+
if idx is not None:
|
| 835 |
+
name = "%s[%d]" % (attr, idx)
|
| 836 |
+
else:
|
| 837 |
+
name = attr
|
| 838 |
+
print("%s- %s: %s" % (self._indent, name, self.repr_of(node)))
|
| 839 |
+
|
| 840 |
+
def repr_of(self, node):
|
| 841 |
+
if node is None:
|
| 842 |
+
return "(none)"
|
| 843 |
+
else:
|
| 844 |
+
result = node.__class__.__name__
|
| 845 |
+
if isinstance(node, ExprNodes.NameNode):
|
| 846 |
+
result += "(type=%s, name=\"%s\")" % (repr(node.type), node.name)
|
| 847 |
+
elif isinstance(node, Nodes.DefNode):
|
| 848 |
+
result += "(name=\"%s\")" % node.name
|
| 849 |
+
elif isinstance(node, Nodes.CFuncDefNode):
|
| 850 |
+
result += "(name=\"%s\")" % node.declared_name()
|
| 851 |
+
elif isinstance(node, ExprNodes.AttributeNode):
|
| 852 |
+
result += "(type=%s, attribute=\"%s\")" % (repr(node.type), node.attribute)
|
| 853 |
+
elif isinstance(node, (ExprNodes.ConstNode, ExprNodes.PyConstNode)):
|
| 854 |
+
result += "(type=%s, value=%r)" % (repr(node.type), node.value)
|
| 855 |
+
elif isinstance(node, ExprNodes.ExprNode):
|
| 856 |
+
t = node.type
|
| 857 |
+
result += "(type=%s)" % repr(t)
|
| 858 |
+
elif node.pos:
|
| 859 |
+
pos = node.pos
|
| 860 |
+
path = pos[0].get_description()
|
| 861 |
+
if '/' in path:
|
| 862 |
+
path = path.split('/')[-1]
|
| 863 |
+
if '\\' in path:
|
| 864 |
+
path = path.split('\\')[-1]
|
| 865 |
+
result += "(pos=(%s:%s:%s))" % (path, pos[1], pos[2])
|
| 866 |
+
|
| 867 |
+
return result
|
| 868 |
+
|
| 869 |
+
if __name__ == "__main__":
|
| 870 |
+
import doctest
|
| 871 |
+
doctest.testmod()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/CmdLine.cpython-311.pyc
ADDED
|
Binary file (17.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/CodeGeneration.cpython-311.pyc
ADDED
|
Binary file (2.02 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/DebugFlags.cpython-311.pyc
ADDED
|
Binary file (497 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/FlowControl.cpython-311.pyc
ADDED
|
Binary file (74.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/Interpreter.cpython-311.pyc
ADDED
|
Binary file (3.45 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/StringEncoding.cpython-311.pyc
ADDED
|
Binary file (20.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/TypeSlots.cpython-311.pyc
ADDED
|
Binary file (54.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (216 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tests/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
# empty file
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Tests/__pycache__/TestJediTyper.cpython-311.pyc
ADDED
|
Binary file (13.7 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2010 Pallets
|
| 2 |
+
|
| 3 |
+
Redistribution and use in source and binary forms, with or without
|
| 4 |
+
modification, are permitted provided that the following conditions are
|
| 5 |
+
met:
|
| 6 |
+
|
| 7 |
+
1. Redistributions of source code must retain the above copyright
|
| 8 |
+
notice, this list of conditions and the following disclaimer.
|
| 9 |
+
|
| 10 |
+
2. Redistributions in binary form must reproduce the above copyright
|
| 11 |
+
notice, this list of conditions and the following disclaimer in the
|
| 12 |
+
documentation and/or other materials provided with the distribution.
|
| 13 |
+
|
| 14 |
+
3. Neither the name of the copyright holder nor the names of its
|
| 15 |
+
contributors may be used to endorse or promote products derived from
|
| 16 |
+
this software without specific prior written permission.
|
| 17 |
+
|
| 18 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| 19 |
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| 20 |
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
| 21 |
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| 22 |
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| 23 |
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
| 24 |
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
| 25 |
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
| 26 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
| 27 |
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| 28 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/METADATA
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.1
|
| 2 |
+
Name: MarkupSafe
|
| 3 |
+
Version: 2.1.5
|
| 4 |
+
Summary: Safely add untrusted strings to HTML/XML markup.
|
| 5 |
+
Home-page: https://palletsprojects.com/p/markupsafe/
|
| 6 |
+
Maintainer: Pallets
|
| 7 |
+
Maintainer-email: contact@palletsprojects.com
|
| 8 |
+
License: BSD-3-Clause
|
| 9 |
+
Project-URL: Donate, https://palletsprojects.com/donate
|
| 10 |
+
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
| 11 |
+
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
|
| 12 |
+
Project-URL: Source Code, https://github.com/pallets/markupsafe/
|
| 13 |
+
Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/
|
| 14 |
+
Project-URL: Chat, https://discord.gg/pallets
|
| 15 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 16 |
+
Classifier: Environment :: Web Environment
|
| 17 |
+
Classifier: Intended Audience :: Developers
|
| 18 |
+
Classifier: License :: OSI Approved :: BSD License
|
| 19 |
+
Classifier: Operating System :: OS Independent
|
| 20 |
+
Classifier: Programming Language :: Python
|
| 21 |
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
| 22 |
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
| 23 |
+
Requires-Python: >=3.7
|
| 24 |
+
Description-Content-Type: text/x-rst
|
| 25 |
+
License-File: LICENSE.rst
|
| 26 |
+
|
| 27 |
+
MarkupSafe
|
| 28 |
+
==========
|
| 29 |
+
|
| 30 |
+
MarkupSafe implements a text object that escapes characters so it is
|
| 31 |
+
safe to use in HTML and XML. Characters that have special meanings are
|
| 32 |
+
replaced so that they display as the actual characters. This mitigates
|
| 33 |
+
injection attacks, meaning untrusted user input can safely be displayed
|
| 34 |
+
on a page.
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
Installing
|
| 38 |
+
----------
|
| 39 |
+
|
| 40 |
+
Install and update using `pip`_:
|
| 41 |
+
|
| 42 |
+
.. code-block:: text
|
| 43 |
+
|
| 44 |
+
pip install -U MarkupSafe
|
| 45 |
+
|
| 46 |
+
.. _pip: https://pip.pypa.io/en/stable/getting-started/
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
Examples
|
| 50 |
+
--------
|
| 51 |
+
|
| 52 |
+
.. code-block:: pycon
|
| 53 |
+
|
| 54 |
+
>>> from markupsafe import Markup, escape
|
| 55 |
+
|
| 56 |
+
>>> # escape replaces special characters and wraps in Markup
|
| 57 |
+
>>> escape("<script>alert(document.cookie);</script>")
|
| 58 |
+
Markup('<script>alert(document.cookie);</script>')
|
| 59 |
+
|
| 60 |
+
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
| 61 |
+
>>> Markup("<strong>Hello</strong>")
|
| 62 |
+
Markup('<strong>hello</strong>')
|
| 63 |
+
|
| 64 |
+
>>> escape(Markup("<strong>Hello</strong>"))
|
| 65 |
+
Markup('<strong>hello</strong>')
|
| 66 |
+
|
| 67 |
+
>>> # Markup is a str subclass
|
| 68 |
+
>>> # methods and operators escape their arguments
|
| 69 |
+
>>> template = Markup("Hello <em>{name}</em>")
|
| 70 |
+
>>> template.format(name='"World"')
|
| 71 |
+
Markup('Hello <em>"World"</em>')
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
Donate
|
| 75 |
+
------
|
| 76 |
+
|
| 77 |
+
The Pallets organization develops and supports MarkupSafe and other
|
| 78 |
+
popular packages. In order to grow the community of contributors and
|
| 79 |
+
users, and allow the maintainers to devote more time to the projects,
|
| 80 |
+
`please donate today`_.
|
| 81 |
+
|
| 82 |
+
.. _please donate today: https://palletsprojects.com/donate
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
Links
|
| 86 |
+
-----
|
| 87 |
+
|
| 88 |
+
- Documentation: https://markupsafe.palletsprojects.com/
|
| 89 |
+
- Changes: https://markupsafe.palletsprojects.com/changes/
|
| 90 |
+
- PyPI Releases: https://pypi.org/project/MarkupSafe/
|
| 91 |
+
- Source Code: https://github.com/pallets/markupsafe/
|
| 92 |
+
- Issue Tracker: https://github.com/pallets/markupsafe/issues/
|
| 93 |
+
- Chat: https://discord.gg/pallets
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: bdist_wheel (0.42.0)
|
| 3 |
+
Root-Is-Purelib: false
|
| 4 |
+
Tag: cp311-cp311-manylinux_2_17_x86_64
|
| 5 |
+
Tag: cp311-cp311-manylinux2014_x86_64
|
| 6 |
+
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
markupsafe
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/flow/tests/gl1.gpickle.bz2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cf8f81ceb5eaaee1621aa60b892d83e596a6173f6f6517359b679ff3daa1b0f8
|
| 3 |
+
size 44623
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/RECORD
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
nvidia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 2 |
+
nvidia/__pycache__/__init__.cpython-311.pyc,,
|
| 3 |
+
nvidia/cublas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 4 |
+
nvidia/cublas/__pycache__/__init__.cpython-311.pyc,,
|
| 5 |
+
nvidia/cublas/include/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 6 |
+
nvidia/cublas/include/__pycache__/__init__.cpython-311.pyc,,
|
| 7 |
+
nvidia/cublas/include/cublas.h,sha256=a0lLqy-k47NuwyDjuueC3W0Mpc908MTU7o5sMJqE-1w,41246
|
| 8 |
+
nvidia/cublas/include/cublasLt.h,sha256=jr9DyHiX6fzzlbnvBZ4kbMEDpr1eAurHZlnHjsnNi-8,79035
|
| 9 |
+
nvidia/cublas/include/cublasXt.h,sha256=CW9dyXYGSUW1wEXrVVyhU6OxBK1PUvMoYdVGlQT7L9A,37380
|
| 10 |
+
nvidia/cublas/include/cublas_api.h,sha256=aJ4b8tkMtQfGgBQ32Nz2q4OaXxayynpCUCDUVMXVOpA,220681
|
| 11 |
+
nvidia/cublas/include/cublas_v2.h,sha256=DrT-TOKePZcfL_ld1ECGv2F30_9KznXxj5WXoABe2v4,8811
|
| 12 |
+
nvidia/cublas/include/nvblas.h,sha256=dXCLR-2oUiJFzLsDtIAK09m42ct4G0HWdYzBUuDPXpc,23341
|
| 13 |
+
nvidia/cublas/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 14 |
+
nvidia/cublas/lib/__pycache__/__init__.cpython-311.pyc,,
|
| 15 |
+
nvidia/cublas/lib/libcublas.so.11,sha256=O4HRcM1hPPnuJNMLSD97bYFw1tMqA1T8IH0JyUOuP2I,94729912
|
| 16 |
+
nvidia/cublas/lib/libcublasLt.so.11,sha256=ttFKdGGz7BmVQn_RebmLkVyfyBBXNmq3v6RoFFGw0wg,574565016
|
| 17 |
+
nvidia/cublas/lib/libnvblas.so.11,sha256=ZHNz0AIKU8cL1E0pUPgfbF7ewgaJmFWACnaqvhrifgI,745240
|
| 18 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 19 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/License.txt,sha256=rW9YU_ugyg0VnQ9Y1JrkmDDC-Mk_epJki5zpCttMbM0,59262
|
| 20 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/METADATA,sha256=mA43HfZFHjjDd8elta6JbTa_ysfzaRIG3x5ynq8HBhw,1506
|
| 21 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/RECORD,,
|
| 22 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/WHEEL,sha256=-kQi_VMfvRQozZJT7HUPMfY-5vLo0LVTmAylNJ3Ft98,106
|
| 23 |
+
nvidia_cublas_cu11-11.11.3.6.dist-info/top_level.txt,sha256=fTkAtiFuL16nUrB9ytDDtpytz2t0B4NvYTnRzwAhO14,7
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia_cublas_cu11-11.11.3.6.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
nvidia
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/__pycache__/utils.cpython-311.pyc
ADDED
|
Binary file (25.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__init__.py
ADDED
|
File without changes
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (213 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/api/__pycache__/meta.cpython-311.pyc
ADDED
|
Binary file (617 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/ATen/templates/DispatchKeyNativeFunctions.cpp
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ${generated_comment}
|
| 2 |
+
${includes}
|
| 3 |
+
${native_functions_include}
|
| 4 |
+
|
| 5 |
+
namespace {
|
| 6 |
+
${helper_fns}
|
| 7 |
+
} // namespace
|
| 8 |
+
|
| 9 |
+
${namespace_prologue}
|
| 10 |
+
|
| 11 |
+
${native_function_definitions}
|
| 12 |
+
|
| 13 |
+
${namespace_epilogue}
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
If you add a file to this directory, you **MUST** update
|
| 2 |
+
`torch/CMakeLists.txt` and add the file as a dependency to
|
| 3 |
+
the `add_custom_command` call.
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/__pycache__/gen_annotated_fn_args.cpython-311.pyc
ADDED
|
Binary file (6.82 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/torchgen/packaged/autograd/__pycache__/gen_view_funcs.cpython-311.pyc
ADDED
|
Binary file (16.4 kB). View file
|
|
|